org.kaaproject.kaa.server.common.admin.KaaRestTemplate.java Source code

Java tutorial

Introduction

Here is the source code for org.kaaproject.kaa.server.common.admin.KaaRestTemplate.java

Source

/*
 * Copyright 2014-2016 CyberVision, Inc.
 *
 * Licensed 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 org.kaaproject.kaa.server.common.admin;

import org.apache.http.HttpHost;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URI;
import java.util.Random;

public class KaaRestTemplate extends RestTemplate {

    private static final Logger logger = LoggerFactory.getLogger(AdminClient.class);

    private static final int DEFAULT_PORT = 80;
    private static final String restApiSuffix = "/kaaAdmin/rest/api/";
    private String[] hosts;
    private int[] ports;
    private String currentUrl;
    private String username;
    private String password;
    private int index;

    public KaaRestTemplate(String host, int port) {
        checkHostPortLists(new String[] { host }, new int[] { port });
    }

    /**
     * Initialize KaaRestTempalte using following format host1:port1,host2:port2.
     */
    public KaaRestTemplate(String hostPortList) {
        if (hostPortList == null) {
            throw new IllegalArgumentException("String of addresses must be not null");
        }

        String[] splitedAddresses = hostPortList.split(",");

        String[] hosts = new String[splitedAddresses.length];
        int[] ports = new int[splitedAddresses.length];

        for (int i = 0; i < hosts.length; i++) {
            String[] separatedAddresses = splitedAddresses[i].split(":");
            hosts[i] = separatedAddresses[0];
            if (separatedAddresses.length == 2) {
                ports[i] = Integer.parseInt(separatedAddresses[1]);
            } else {
                ports[i] = DEFAULT_PORT;
            }
        }
        checkHostPortLists(hosts, ports);
    }

    private void checkHostPortLists(String[] hosts, int[] ports) {
        if (hosts == null) {
            throw new IllegalArgumentException("Parameter hosts can't be null.");
        }

        if (ports == null) {
            throw new IllegalArgumentException("Parameter ports can't be null.");
        }

        if (hosts.length != ports.length) {
            throw new IllegalArgumentException("Length of arrays of hosts " + "and ports must be the same length");
        } else {
            this.hosts = hosts;
            this.ports = ports;
            index = new Random().nextInt(hosts.length);
            setNewRequestFactory(index);
        }
    }

    public String getUrl() {
        return currentUrl;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,
            ResponseExtractor<T> responseExtractor) throws ResourceAccessException {
        int maxRetry = hosts.length;
        while (true) {
            try {
                return super.doExecute(url, method, requestCallback, responseExtractor);
            } catch (ResourceAccessException ex) {
                logger.info("Connect to ({}:{}) failed", getCurHost(), getCurPort(), ex);
                boolean isRequestFactorySet = false;
                while (!isRequestFactorySet) {
                    if (index < hosts.length - 1) {
                        index++;
                    } else {
                        index = 0;
                    }
                    logger.info("Trying connect to ({}:{})", getCurHost(), getCurPort(), ex);
                    if (maxRetry <= 0) {
                        logger.error("Failed to connect to ({}:{})", getCurHost(), getCurPort(), ex);
                        throw new ResourceAccessException(
                                "I/O error on " + method.name() + " request for \"" + url + "\":" + ex.getMessage(),
                                new IOException(ex));
                    } else {
                        maxRetry--;
                    }
                    try {
                        setNewRequestFactory(index);
                    } catch (Exception exception) {
                        logger.info("Failed to initialize new request factory ({}:{})", getCurHost(), getCurPort(),
                                exception);
                        continue;
                    }
                    url = updateUrl(url);
                    isRequestFactorySet = true;
                }
            } catch (RestClientException ex) {
                throw ex;
            }
        }
    }

    private URI updateUrl(URI url) {
        String currentUri = url.toString();

        int sufixPartIdx = currentUri.indexOf(restApiSuffix);

        String defaultUriPartWithVariableHostPort = currentUri.substring(0, sufixPartIdx);
        String sufixPart = currentUri.substring(sufixPartIdx);

        defaultUriPartWithVariableHostPort = defaultUriPartWithVariableHostPort.replaceFirst(url.getHost(),
                getCurHost());
        defaultUriPartWithVariableHostPort = defaultUriPartWithVariableHostPort
                .replaceFirst(String.valueOf(url.getPort()), String.valueOf(getCurPort()));

        return URI.create(defaultUriPartWithVariableHostPort + sufixPart);
    }

    private int getCurPort() {
        return ports[index];
    }

    private String getCurHost() {
        return hosts[index];
    }

    private void setNewRequestFactory(int index) {
        String host = hosts[index];
        int port = ports[index];
        setRequestFactory(new HttpComponentsRequestFactoryBasicAuth(new HttpHost(host, port, "http")));
        currentUrl = "http://" + host + ":" + port + restApiSuffix;
        if (username != null && password != null) {
            login(username, password);
        }
    }

    /**
     * Login to Kaa server.
     *
     * @param username user name
     * @param password password
     */
    public void login(String username, String password) {
        this.username = username;
        this.password = password;
        HttpComponentsRequestFactoryBasicAuth requestFactory = (HttpComponentsRequestFactoryBasicAuth) getRequestFactory();
        requestFactory.setCredentials(username, password);
    }

}