com.treasuredata.client.TDClientConfig.java Source code

Java tutorial

Introduction

Here is the source code for com.treasuredata.client.TDClientConfig.java

Source

/*
 * 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 com.treasuredata.client;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.io.Files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Properties;

/**
 * TD Client configuration
 */
public class TDClientConfig {
    public static final String ENV_TD_CLIENT_APIKEY = "TD_API_KEY";

    /**
     * Keys for configuring TDClient with a properties file (or System properties)
     */
    public static enum Type {
        APIKEY("td.client.apikey", "API key to access Treasure Data."), USER("td.client.user",
                "Account e-mail address (unnecessary if apikey is set)"), PASSOWRD("td.client.password",
                        "Account password (unnecessary if apikey is set"), USESSL("td.client.usessl",
                                "Use SSL encryption"), API_ENDPOINT("td.client.endpoint",
                                        "TD API end point (e.g., api.treasuredata.com"), API_PORT("td.client.port",
                                                "TD API port number"), RETRY_LIMIT("td.client.retry.limit",
                                                        "The maximum nubmer of API request retry"), RETRY_INITIAL_INTERVAL_MILLIS(
                                                                "td.client.retry.initial-interval",
                                                                "backoff retry interval = (interval) * (multiplier) ^ (retry count)"), RETRY_MAX_INTERVAL_MILLIS(
                                                                        "td.client.retry.max-interval",
                                                                        "max retry interval"), RETRY_MULTIPLIER(
                                                                                "td.client.retry.multiplier",
                                                                                "retry interval multiplier"), CONNECT_TIMEOUT_MILLIS(
                                                                                        "td.client.connect-timeout",
                                                                                        "connection timeout before reaching the API"), IDLE_TIMEOUT_MILLIS(
                                                                                                "td.client.idle-timeout",
                                                                                                "idle connection timeout when no data is coming from API"), REQUEST_TIMEOUT_MILLIS(
                                                                                                        "td.client.request-timeout",
                                                                                                        "timeout during executing a request"), CONNECTION_POOL_SIZE(
                                                                                                                "td.client.connection-pool-size",
                                                                                                                "connection pool size"), REQUEST_BUFFER_SIZE(
                                                                                                                        "td.client.request-buffer-size",
                                                                                                                        "request buffer size"), RESPONSE_BUFFER_SIZE(
                                                                                                                                "td.client.response-buffer-size",
                                                                                                                                "response buffer size"), MAX_CONTENT_LENGTH(
                                                                                                                                        "td.client.max-content-length",
                                                                                                                                        "maximum response body content length"), PROXY_HOST(
                                                                                                                                                "td.client.proxy.host",
                                                                                                                                                "Proxy host (e.g., myproxy.com)"), PROXY_PORT(
                                                                                                                                                        "td.client.proxy.port",
                                                                                                                                                        "Proxy port number"), PROXY_USER(
                                                                                                                                                                "td.client.proxy.user",
                                                                                                                                                                "Proxy user name"), PROXY_PASSWORD(
                                                                                                                                                                        "td.client.proxy.password",
                                                                                                                                                                        "Proxy paassword"), PROXY_USESSL(
                                                                                                                                                                                "td.client.proxy.usessl",
                                                                                                                                                                                "Use SSL for proxy");

        public final String key;
        public final String description;

        Type(String key, String description) {
            this.key = key;
            this.description = description;
        }
    }

    public static List<Type> knownProperties() {
        ImmutableList.Builder<Type> builder = ImmutableList.builder();
        for (Type t : Type.values()) {
            builder.add(t);
        }
        return builder.build();
    }

    /**
     * endpoint URL (e.g., api.treasuredata.com, api.ybi.idcfcloud.net)
     */
    public final String endpoint;
    public final Optional<Integer> port;
    public final Optional<String> apiKey;
    public final Optional<String> user;
    public final Optional<String> password;
    public final Optional<ProxyConfig> proxy;
    public final boolean useSSL;
    public final int retryLimit;
    public final int retryInitialIntervalMillis;
    public final int retryMaxIntervalMillis;
    public final double retryMultiplier;
    public final int connectTimeoutMillis;
    public final int idleTimeoutMillis;
    public final int requestTimeoutMillis;
    public final int connectionPoolSize;
    public final Multimap<String, String> headers;
    public final Optional<Integer> requestBufferSize;
    public final Optional<Integer> responseBufferSize;
    public final Optional<Integer> maxContentLength;

    @JsonCreator
    TDClientConfig(Optional<String> endpoint, Optional<Integer> port, boolean useSSL, Optional<String> apiKey,
            Optional<String> user, Optional<String> password, Optional<ProxyConfig> proxy, int retryLimit,
            int retryInitialIntervalMillis, int retryMaxIntervalMillis, double retryMultiplier,
            int connectTimeoutMillis, int idleTimeoutMillis, int requestTimeoutMillis, int connectionPoolSize,
            Multimap<String, String> headers, Optional<Integer> requestBufferSize,
            Optional<Integer> responseBufferSize, Optional<Integer> maxContentLength) {
        this.endpoint = endpoint.or("api.treasuredata.com");
        this.port = port;
        this.useSSL = useSSL;
        this.apiKey = apiKey;
        this.user = user;
        this.password = password;
        this.proxy = proxy;
        this.retryLimit = retryLimit;
        this.retryInitialIntervalMillis = retryInitialIntervalMillis;
        this.retryMaxIntervalMillis = retryMaxIntervalMillis;
        this.retryMultiplier = retryMultiplier;
        this.connectTimeoutMillis = connectTimeoutMillis;
        this.idleTimeoutMillis = idleTimeoutMillis;
        this.requestTimeoutMillis = requestTimeoutMillis;
        this.connectionPoolSize = connectionPoolSize;
        this.headers = headers;
        this.requestBufferSize = requestBufferSize;
        this.responseBufferSize = responseBufferSize;
        this.maxContentLength = maxContentLength;
    }

    public TDClientConfig withApiKey(String apikey) {
        return withApiKey(Optional.of(apikey));
    }

    public TDClientConfig withApiKey(Optional<String> apikey) {
        return new TDClientConfig(Optional.of(endpoint), port, useSSL, apikey, user, password, proxy, retryLimit,
                retryInitialIntervalMillis, retryMaxIntervalMillis, retryMultiplier, connectTimeoutMillis,
                idleTimeoutMillis, requestTimeoutMillis, connectionPoolSize, headers, requestBufferSize,
                responseBufferSize, maxContentLength);
    }

    private static <V> void saveProperty(Properties p, Type config, V value) {
        if (value == null) {
            return;
        }

        if (value instanceof Optional) {
            Optional<?> opt = (Optional<?>) value;
            if (opt.isPresent()) {
                Object v = opt.get();
                saveProperty(p, config, v);
            }
        } else {
            p.setProperty(config.key, value.toString());
        }
    }

    /**
     * Output this configuration as a Properties object
     *
     * @return
     */
    public Properties toProperties() {
        Properties p = new Properties();
        saveProperty(p, Type.API_ENDPOINT, endpoint);
        saveProperty(p, Type.API_PORT, port);
        saveProperty(p, Type.USESSL, useSSL);
        saveProperty(p, Type.APIKEY, apiKey);
        saveProperty(p, Type.USER, user);
        saveProperty(p, Type.PASSOWRD, password);
        if (proxy.isPresent()) {
            ProxyConfig pc = proxy.get();
            saveProperty(p, Type.PROXY_HOST, pc.getHost());
            saveProperty(p, Type.PROXY_PORT, pc.getPort());
            saveProperty(p, Type.PROXY_USER, pc.getUser());
            saveProperty(p, Type.PROXY_PASSWORD, pc.getPassword());
            saveProperty(p, Type.PROXY_USESSL, pc.useSSL());
        }
        saveProperty(p, Type.RETRY_LIMIT, retryLimit);
        saveProperty(p, Type.RETRY_INITIAL_INTERVAL_MILLIS, retryInitialIntervalMillis);
        saveProperty(p, Type.RETRY_MAX_INTERVAL_MILLIS, retryMaxIntervalMillis);
        saveProperty(p, Type.RETRY_MULTIPLIER, retryMultiplier);
        saveProperty(p, Type.CONNECT_TIMEOUT_MILLIS, connectTimeoutMillis);
        saveProperty(p, Type.REQUEST_TIMEOUT_MILLIS, requestTimeoutMillis);
        saveProperty(p, Type.CONNECTION_POOL_SIZE, connectionPoolSize);
        saveProperty(p, Type.MAX_CONTENT_LENGTH, maxContentLength);
        saveProperty(p, Type.REQUEST_BUFFER_SIZE, requestBufferSize);
        saveProperty(p, Type.RESPONSE_BUFFER_SIZE, responseBufferSize);
        saveProperty(p, Type.MAX_CONTENT_LENGTH, maxContentLength);
        return p;
    }

    private static Logger logger = LoggerFactory.getLogger(TDClientConfig.class);
    private static Properties tdConf;

    /**
     * Get the default TDClientConfig by reading $HOME/.td/td.conf file.
     *
     * @return
     * @throws IOException
     * @throws TDClientException
     */
    static Properties getTDConfProperties() {
        if (tdConf == null) {
            tdConf = readTDConf();
        }
        return tdConf;
    }

    /**
     * Read apikey, user (e-mail address) and password from $HOME/.td/td.conf
     *
     * @return
     * @throws IOException
     */
    public static Properties readTDConf() {
        Properties p = new Properties();
        File file = new File(System.getProperty("user.home", "./"), String.format(".td/td.conf"));
        if (!file.exists()) {
            logger.warn(String.format("config file %s is not found", file));
            return p;
        }
        return readTDConf(file);
    }

    public static Properties readTDConf(File file) {
        Properties p = new Properties();
        logger.info(String.format("Reading configuration file: %s", file));
        try {
            List<String> lines = Files.readLines(file, StandardCharsets.UTF_8);
            StringBuilder extracted = new StringBuilder();
            for (String line : lines) {
                String trimmed = line.trim();
                if (trimmed.startsWith("[") || trimmed.startsWith("#")) {
                    continue; // skip [... ] line or comment line
                }
                extracted.append(line.trim());
                extracted.append("\n");
            }
            String props = extracted.toString();
            p.load(new StringReader(props));

            // Parse endpoint url if necessary
            if (p.containsKey("endpoint")) {
                parseEndpoint(p);
            }
            return p;
        } catch (IOException e) {
            throw new TDClientException(TDClientException.ErrorType.INVALID_CONFIGURATION,
                    String.format("Failed to read config file: %s", file), e);
        }
    }

    private static void parseEndpoint(Properties p) {
        String endpoint = p.getProperty("endpoint");
        URI uri;
        try {
            uri = new URI(endpoint);
        } catch (URISyntaxException ignore) {
            // The endpoint was not a URL, let it be as is
            return;
        }

        int defaultPort;
        boolean useSsl;

        switch (uri.getScheme()) {
        case "http":
            defaultPort = 80;
            useSsl = false;
            break;
        case "https":
            defaultPort = 443;
            useSsl = true;
            break;
        default:
            throw new IllegalArgumentException("Invalid endpoint scheme: " + uri.getScheme());
        }

        p.setProperty("endpoint", uri.getHost());

        if (!p.containsKey("port")) {
            int port = (uri.getPort() == -1) ? defaultPort : uri.getPort();
            p.setProperty("port", Integer.toString(port));
        }

        if (!p.contains("usessl")) {
            p.setProperty("usessl", Boolean.toString(useSsl));
        }
    }
}