com.nubits.nubot.trading.wrappers.BitcoinCoIDWrapper.java Source code

Java tutorial

Introduction

Here is the source code for com.nubits.nubot.trading.wrappers.BitcoinCoIDWrapper.java

Source

/*
 * Copyright (C) 2015 Nu Development Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package com.nubits.nubot.trading.wrappers;

import com.nubits.nubot.bot.Global;
import com.nubits.nubot.exchanges.Exchange;
import com.nubits.nubot.global.Constant;
import com.nubits.nubot.global.Settings;
import com.nubits.nubot.models.*;
import com.nubits.nubot.models.Currency;
import com.nubits.nubot.trading.*;
import com.nubits.nubot.trading.keys.ApiKeys;
import com.nubits.nubot.utils.Utils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.text.NumberFormat;
import java.util.*;

/**
 * Created by sammoth on 19/01/15.
 */
public class BitcoinCoIDWrapper implements TradeInterface {

    private static final Logger LOG = LoggerFactory.getLogger(BitcoinCoIDWrapper.class.getName());
    //Class fields
    private ApiKeys keys;
    protected BitcoinCoIDService service;
    private Exchange exchange;
    private final String SIGN_HASH_FUNCTION = "HmacSHA512";
    private final String ENCODING = "UTF-8";
    //API Paths
    private final String API_BASE_URL = "https://vip.bitcoin.co.id/tapi";
    private final String API_TICKER_URL = "https://vip.bitcoin.co.id/api/";
    private final String API_TICKER = "ticker";
    private final String API_GET_INFO = "getInfo";
    private final String API_TRADE = "trade";
    private final String API_OPEN_ORDERS = "openOrders";
    private final String API_CANCEL_ORDER = "cancelOrder";
    private final String API_TRADE_HISTORY = "tradeHistory";
    //Errors
    private ErrorManager errors = new ErrorManager();
    private final String TOKEN_ERR = "error";
    private final String TOKEN_BAD_RETURN = "No Connection With Exchange";
    private final String TOKEN_CODE = "success";

    public BitcoinCoIDWrapper(ApiKeys keys, Exchange exchange) {
        this.keys = keys;
        this.exchange = exchange;
        service = new BitcoinCoIDService(keys);
        setupErrors();
    }

    private void setupErrors() {
        errors.setExchangeName(exchange);
    }

    private ApiResponse getQuery(String url, String method, HashMap<String, String> query_args, boolean needAuth,
            boolean isGet) {
        ApiResponse apiResponse = new ApiResponse();
        String queryResult = query(url, method, query_args, needAuth, isGet);
        if (queryResult == null) {
            apiResponse.setError(errors.nullReturnError);
            return apiResponse;
        }
        if (queryResult.equals(TOKEN_BAD_RETURN)) {
            apiResponse.setError(errors.noConnectionError);
            return apiResponse;
        }
        JSONParser parser = new JSONParser();

        try {
            JSONObject httpAnswerJson = (JSONObject) (parser.parse(queryResult));
            int code = 0;
            try {
                code = Integer.parseInt(httpAnswerJson.get(TOKEN_CODE).toString());
            } catch (ClassCastException cce) {
                apiResponse.setError(errors.genericError);
            }

            if (code == 0) {
                String errorMessage = (String) httpAnswerJson.get(TOKEN_ERR);
                ApiError apiError = errors.apiReturnError;
                apiError.setDescription(errorMessage);
                //LOG.error("AllCoin API returned an error : " + errorMessage);
                apiResponse.setError(apiError);
            } else {
                apiResponse.setResponseObject(httpAnswerJson);
            }
        } catch (ClassCastException cce) {
            //if casting to a JSON object failed, try a JSON Array
            try {
                JSONArray httpAnswerJson = (JSONArray) (parser.parse(queryResult));
                apiResponse.setResponseObject(httpAnswerJson);
            } catch (ParseException pe) {
                LOG.error("httpResponse: " + queryResult + " \n" + pe.toString());
                apiResponse.setError(errors.parseError);
            }
        } catch (ParseException pe) {
            LOG.error("httpResponse: " + queryResult + " \n" + pe.toString());
            apiResponse.setError(errors.parseError);
            return apiResponse;
        }
        return apiResponse;
    }

    @Override
    public ApiResponse getAvailableBalances(CurrencyPair pair) {
        return getBalanceImpl(null, pair);
    }

    @Override
    public ApiResponse getAvailableBalance(Currency currency) {
        return getBalanceImpl(currency, null);
    }

    private ApiResponse getBalanceImpl(Currency currency, CurrencyPair pair) {
        ApiResponse apiResponse = new ApiResponse();
        boolean isGet = false;
        String url = API_BASE_URL;
        String method = API_GET_INFO;
        HashMap<String, String> query_args = new HashMap<>();

        ApiResponse response = getQuery(url, method, query_args, true, isGet);
        if (response.isPositive()) {
            JSONObject httpAnswerJson = (JSONObject) response.getResponseObject();
            JSONObject data = (JSONObject) httpAnswerJson.get("return");
            JSONObject balances = (JSONObject) data.get("balance");
            if (currency == null) { //get the balances for the pair
                double pegAvail = Double
                        .parseDouble(balances.get(pair.getPaymentCurrency().getCode().toLowerCase()).toString());
                Amount PEGAvail = new Amount(pegAvail, pair.getPaymentCurrency());
                double nbtAvail = Double
                        .parseDouble(balances.get(pair.getOrderCurrency().getCode().toLowerCase()).toString());
                Amount NBTAvail = new Amount(nbtAvail, pair.getOrderCurrency());
                double pegOnOrder = 0;
                double nbtOnOrder = 0;
                ArrayList<Order> orders = (ArrayList) getActiveOrdersToCountLockedBalance(pair).getResponseObject();
                if (orders == null) {
                    apiResponse.setError(errors.nullReturnError);
                    return apiResponse;
                }
                for (Iterator<Order> order = orders.iterator(); order.hasNext();) {
                    Order thisOrder = order.next();
                    if (thisOrder.getType().equals(Constant.SELL)) {
                        nbtOnOrder += thisOrder.getAmount().getQuantity();
                    } else {
                        pegOnOrder += Utils.round(thisOrder.getAmount().getQuantity(), Settings.DEFAULT_PRECISION);
                    }
                }
                Amount PEGonOrder = new Amount(pegOnOrder, pair.getPaymentCurrency());
                Amount NBTonOrder = new Amount(nbtOnOrder, pair.getOrderCurrency());
                PairBalance balance = new PairBalance(PEGAvail, NBTAvail, PEGonOrder, NBTonOrder);
                apiResponse.setResponseObject(balance);
            } else {
                double balance = Double.parseDouble(balances.get(currency.getCode().toLowerCase()).toString());
                Amount total = new Amount(balance, currency);
                apiResponse.setResponseObject(total);
            }
        } else {
            apiResponse = response;
        }
        return apiResponse;
    }

    @Override
    public ApiResponse getLastPrice(CurrencyPair pair) {
        ApiResponse apiResponse = new ApiResponse();
        String url = API_TICKER_URL + pair.toStringSep() + "/" + API_TICKER;
        HashMap<String, String> query_args = new HashMap<>();
        boolean isGet = true;

        double last = -1;
        double ask = -1;
        double bid = -1;
        Ticker ticker = new Ticker();

        String queryResult = query(url, "", query_args, false, isGet);
        JSONParser parser = new JSONParser();
        JSONObject httpAnswerJson = null;
        try {
            httpAnswerJson = (JSONObject) parser.parse(queryResult);
        } catch (ParseException pe) {
            LOG.error(pe.toString());
            ApiError error = errors.apiReturnError;
            error.setDescription("Error parsing ticker response");
            apiResponse.setError(error);
            return apiResponse;
        }
        JSONObject tick = (JSONObject) httpAnswerJson.get("ticker");
        last = Double.parseDouble(tick.get("last").toString());
        ask = Double.parseDouble(tick.get("sell").toString());
        bid = Double.parseDouble(tick.get("buy").toString());
        ticker.setLast(last);
        ticker.setAsk(ask);
        ticker.setBid(bid);
        apiResponse.setResponseObject(ticker);
        return apiResponse;
    }

    @Override
    public ApiResponse sell(CurrencyPair pair, double amount, double rate) {
        return enterOrder(Constant.SELL, pair, amount, rate);
    }

    @Override
    public ApiResponse buy(CurrencyPair pair, double amount, double rate) {
        return enterOrder(Constant.BUY, pair, amount, rate);
    }

    private ApiResponse enterOrder(String type, CurrencyPair pair, double amount, double price) {
        ApiResponse apiResponse = new ApiResponse();
        String url = API_BASE_URL;
        String method = API_TRADE;
        HashMap<String, String> args = new HashMap<>();
        boolean isGet = false;
        String order_id = null;

        args.put("pair", pair.toStringSep());
        args.put("type", type.toLowerCase());
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMinimumFractionDigits(8);
        args.put("price", nf.format(price));
        if (type.equals(Constant.SELL)) {
            args.put(pair.getPaymentCurrency().getCode().toLowerCase(), nf.format(amount * price));
            args.put(pair.getOrderCurrency().getCode().toLowerCase(), nf.format(amount));
        } else {
            args.put(pair.getPaymentCurrency().getCode().toLowerCase(), nf.format(amount * price));
        }

        ApiResponse response = getQuery(url, method, args, true, isGet);
        if (response.isPositive()) {
            JSONObject httpAnswerJson = (JSONObject) response.getResponseObject();
            JSONObject data = (JSONObject) httpAnswerJson.get("return");
            order_id = data.get("order_id").toString();
            apiResponse.setResponseObject(order_id);
        } else {
            apiResponse = response;
        }
        return apiResponse;
    }

    @Override
    public ApiResponse getActiveOrders() {
        return getActiveOrdersImpl(null, false);
    }

    @Override
    public ApiResponse getActiveOrders(CurrencyPair pair) {
        return getActiveOrdersImpl(pair, false);
    }

    public ApiResponse getActiveOrdersToCountLockedBalance(CurrencyPair pair) {
        return getActiveOrdersImpl(pair, true);
    }

    private ApiResponse getActiveOrdersImpl(CurrencyPair pair, boolean convertBuyAmounts) {
        ApiResponse apiResponse = new ApiResponse();
        String url = API_BASE_URL;
        String method = API_OPEN_ORDERS;
        ArrayList<Order> orderList = new ArrayList<>();
        HashMap<String, String> query_args = new HashMap<>();
        boolean isGet = false;

        //only handles openOrders with given pair

        if (pair != null) {
            query_args.put("pair", pair.toStringSep());
        } else {
            pair = Global.options.getPair();
            query_args.put("pair", pair.toStringSep());
        }

        ApiResponse response = getQuery(url, method, query_args, true, isGet);
        if (response.isPositive()) {
            JSONObject httpAnswerJson = (JSONObject) response.getResponseObject();
            JSONObject data = (JSONObject) httpAnswerJson.get("return");
            JSONArray orders = (JSONArray) data.get("orders");
            if (orders != null) {
                for (Iterator<JSONObject> order = orders.iterator(); order.hasNext();) {
                    JSONObject thisOrder = order.next();
                    orderList.add(parseOrder(thisOrder, pair, convertBuyAmounts));
                }
            }
            apiResponse.setResponseObject(orderList);
        } else {
            apiResponse = response;
        }
        return apiResponse;
    }

    private Order parseOrder(JSONObject in, CurrencyPair cp, boolean convertBuyAmounts) {
        Order out = new Order();

        out.setId(in.get("order_id").toString());
        Date insertedDate = new Date(Long.parseLong(in.get("submit_time").toString()) * 1000L);
        out.setInsertedDate(insertedDate);
        out.setType(in.get("type").toString().equals("buy") ? Constant.BUY : Constant.SELL);
        String cur;
        Amount amount;
        Amount price = new Amount(Double.parseDouble(in.get("price").toString()),
                Global.options.getPair().getPaymentCurrency());
        if (out.getType().equals(Constant.BUY)) {
            cur = Global.options.getPair().getPaymentCurrency().getCode().toLowerCase();
            if (!convertBuyAmounts) {
                amount = new Amount(Double.parseDouble(in.get("order_" + cur).toString()) / price.getQuantity(),
                        Global.options.getPair().getOrderCurrency());
            } else {
                amount = new Amount(Double.parseDouble(in.get("order_" + cur).toString()),
                        Global.options.getPair().getPaymentCurrency()); //Leave the amount expressed in PEG currency, to count orders
            }
        } else {
            cur = Global.options.getPair().getOrderCurrency().getCode().toLowerCase();
            amount = new Amount(Double.parseDouble(in.get("order_" + cur).toString()),
                    Global.options.getPair().getOrderCurrency());
        }
        out.setPair(cp);

        out.setAmount(amount);
        out.setPrice(price);
        out.setCompleted(amount.getQuantity() == Double.parseDouble(in.get("remain_" + cur).toString()));

        return out;
    }

    @Override
    public ApiResponse getOrderDetail(String orderID) {
        ApiResponse apiResponse = new ApiResponse();

        ApiResponse getActiveOrdersResponse = getActiveOrders();

        if (getActiveOrdersResponse.isPositive()) {
            ArrayList<Order> activeOrders = (ArrayList<Order>) getActiveOrdersResponse.getResponseObject();
            boolean found = false;
            for (Iterator<Order> order = activeOrders.iterator(); order.hasNext();) {
                Order thisOrder = order.next();
                if (thisOrder.getId().equals(orderID)) {
                    found = true;
                    apiResponse.setResponseObject(thisOrder);
                    break;
                }
            }

            if (!found) {
                ApiError err = errors.apiReturnError;
                err.setDescription("Order " + orderID + " does not exists");
                apiResponse.setError(err);
            }
        } else {
            apiResponse = getActiveOrdersResponse;
        }

        return apiResponse;
    }

    @Override
    public ApiResponse cancelOrder(String orderID, CurrencyPair pair) {
        ApiResponse apiResponse = new ApiResponse();
        String url = API_BASE_URL;
        String method = API_CANCEL_ORDER;
        boolean isGet = false;
        HashMap<String, String> query_args = new HashMap<>();

        query_args.put("pair", pair.toStringSep());
        query_args.put("order_id", orderID);

        ApiResponse orderDetailResponse = getOrderDetail(orderID);
        Order currentOrder;
        if (!orderDetailResponse.isPositive()) {
            return orderDetailResponse;
        }

        currentOrder = (Order) orderDetailResponse.getResponseObject();
        query_args.put("type", currentOrder.getType().toLowerCase());

        ApiResponse response = getQuery(url, method, query_args, true, isGet);
        if (response.isPositive()) {
            JSONObject httpAnswerJson = (JSONObject) response.getResponseObject();
            JSONObject data = (JSONObject) httpAnswerJson.get("return");
            if (data.get("order_id").toString().equals(orderID)) {
                apiResponse.setResponseObject(true);
            } else {
                apiResponse.setResponseObject(false);
            }
        } else {
            apiResponse = response;
        }

        return apiResponse;
    }

    @Override
    public ApiResponse getTxFee() {
        double defaultFee = 0.0;
        return new ApiResponse(true, defaultFee, null);
    }

    @Override
    public ApiResponse getTxFee(CurrencyPair pair) {
        double defaultFee = 0.0;
        return new ApiResponse(true, defaultFee, null);
    }

    @Override
    public ApiResponse getLastTrades(CurrencyPair pair) {
        return getLastTradesImpl(pair, 0);
    }

    @Override
    public ApiResponse getLastTrades(CurrencyPair pair, long startTime) {
        return getLastTradesImpl(pair, startTime);
    }

    private ApiResponse getLastTradesImpl(CurrencyPair pair, long startTime) {
        ApiResponse apiResponse = new ApiResponse();
        String url = API_BASE_URL;
        String method = API_TRADE_HISTORY;
        boolean isGet = false;
        HashMap<String, String> query_args = new HashMap<>();
        ArrayList<Trade> tradeList = new ArrayList<>();

        query_args.put("pair", pair.toStringSep());
        if (startTime > 0) {
            query_args.put("since", Objects.toString(startTime));
        }

        ApiResponse response = getQuery(url, method, query_args, true, isGet);
        if (response.isPositive()) {
            JSONObject httpAnswerJson = (JSONObject) response.getResponseObject();
            JSONObject data = (JSONObject) httpAnswerJson.get("return");
            JSONArray trades = (JSONArray) data.get("trades");
            for (Iterator<JSONObject> trade = trades.iterator(); trade.hasNext();) {
                JSONObject thisTrade = trade.next();
                tradeList.add(parseTrade(thisTrade, pair));
            }
            apiResponse.setResponseObject(tradeList);
        } else {
            apiResponse = response;
        }

        return apiResponse;
    }

    private Trade parseTrade(JSONObject in, CurrencyPair pair) {
        Trade out = new Trade();

        out.setId(in.get("trade_id").toString());
        out.setType(in.get("type").toString().equals("buy") ? Constant.BUY : Constant.SELL);
        Date tradeDate = new Date(Long.parseLong(in.get("trade_time").toString()) * 1000L);
        out.setDate(tradeDate);
        out.setExchangeName(Global.exchange.getName());
        Amount fee = new Amount(Double.parseDouble(in.get("fee").toString()), pair.getPaymentCurrency());
        out.setFee(fee);
        Amount amount = new Amount(
                Double.parseDouble(in.get(pair.getOrderCurrency().getCode().toLowerCase()).toString()),
                pair.getOrderCurrency());
        out.setAmount(amount);
        Amount price = new Amount(Double.parseDouble(in.get("price").toString()), pair.getPaymentCurrency());
        out.setPrice(price);
        out.setPair(pair);

        return out;
    }

    @Override
    public ApiResponse isOrderActive(String id) {
        ApiResponse apiResponse = new ApiResponse();
        apiResponse = getOrderDetail(id);
        if (apiResponse.isPositive()) {
            Order order = (Order) apiResponse.getResponseObject();
            if (order.isCompleted()) {
                apiResponse.setResponseObject(true);
            } else {
                apiResponse.setResponseObject(false);
            }
        } else {
            apiResponse.setResponseObject(false);
        }
        return apiResponse;
    }

    @Override
    public ApiResponse clearOrders(CurrencyPair pair) {
        ApiResponse apiResponse = new ApiResponse();
        apiResponse.setResponseObject(true);
        ApiResponse getOrders = getActiveOrders();

        if (getOrders.isPositive()) {
            ArrayList<Order> orders = (ArrayList) getOrders.getResponseObject();
            for (Iterator<Order> order = orders.iterator(); order.hasNext();) {
                Order o = order.next();
                String id = o.getId();
                ApiResponse r = cancelOrder(id, pair);
                boolean posi = r.isPositive();
                if (!posi) {
                    apiResponse.setResponseObject(false);
                } else {
                    apiResponse.setResponseObject(r.getResponseObject());
                }
            }
        } else {
            apiResponse = getOrders;
        }

        return apiResponse;
    }

    @Override
    public ApiError getErrorByCode(int code) {
        return null;
    }

    @Override
    public String getUrlConnectionCheck() {
        return API_BASE_URL;
    }

    @Override
    public String query(String base, String method, AbstractMap<String, String> args, boolean needAuth,
            boolean isGet) {
        String queryResult = TOKEN_BAD_RETURN; //Will return this string in case it fails
        if (exchange.getLiveData().isConnected()) {
            if (exchange.isFree()) {
                exchange.setBusy();
                queryResult = service.executeQuery(base, method, args, needAuth, isGet);
                exchange.setFree();
            } else {
                //Another thread is probably executing a query. Init the retry procedure
                long sleeptime = Settings.RETRY_SLEEP_INCREMENT * 1;
                int counter = 0;
                long startTimeStamp = System.currentTimeMillis();
                LOG.debug(method + " blocked, another call is being processed ");
                boolean exit = false;
                do {
                    counter++;
                    sleeptime = counter * Settings.RETRY_SLEEP_INCREMENT; //Increase sleep time
                    sleeptime += (int) (Math.random() * 200) - 100;// Add +- 100 ms random to facilitate competition
                    LOG.debug(
                            "Retrying for the " + counter + " time. Sleep for " + sleeptime + "; Method=" + method);
                    try {
                        Thread.sleep(sleeptime);
                    } catch (InterruptedException e) {
                        LOG.error(e.toString());
                    }

                    //Try executing the call
                    if (exchange.isFree()) {
                        LOG.debug("Finally the exchange is free, executing query after " + counter
                                + " attempt. Method=" + method);
                        exchange.setBusy();
                        queryResult = service.executeQuery(base, method, args, needAuth, isGet);
                        exchange.setFree();
                        break; //Exit loop
                    } else {
                        LOG.debug("Exchange still busy : " + counter + " .Will retry soon; Method=" + method);
                        exit = false;
                    }
                    if (System.currentTimeMillis() - startTimeStamp >= Settings.TIMEOUT_QUERY_RETRY) {
                        exit = true;
                        LOG.error(
                                "Method=" + method + " failed too many times and timed out. attempts = " + counter);
                    }
                } while (!exit);
            }
        } else {
            LOG.error("The bot will not execute the query, there is no connection with" + exchange.getName());
            queryResult = TOKEN_BAD_RETURN;
        }
        return queryResult;
    }

    @Override
    public void setKeys(ApiKeys keys) {
        this.keys = keys;
    }

    @Override
    public void setExchange(Exchange exchange) {
        this.exchange = exchange;
    }

    @Override
    public void setApiBaseUrl(String apiBaseUrl) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public ApiResponse getOrderBook(CurrencyPair pair) {
        throw new UnsupportedOperationException("BitcoinCoIDWrapper.getOrderBook() not implemented yet.");
    }

    private class BitcoinCoIDService implements ServiceInterface {

        protected ApiKeys keys;

        public BitcoinCoIDService(ApiKeys keys) {
            this.keys = keys;
        }

        @Override
        public String executeQuery(String base, String method, AbstractMap<String, String> args, boolean needAuth,
                boolean isGet) {
            HttpsURLConnection connection = null;
            String url = base;
            URL queryUrl = null;
            String post_data = "";
            boolean httpError = false;
            String output;
            int response = 200;
            String answer = null;

            try {
                queryUrl = new URL(url);
            } catch (MalformedURLException mal) {
                LOG.error(mal.toString());
                return null;
            }

            if (needAuth) {

                String nonce = Objects.toString(System.currentTimeMillis());
                LOG.trace("computed nonce =" + nonce);

                args.put("nonce", nonce);
                args.put("method", method);
                post_data = TradeUtils.buildQueryString(args, ENCODING);
            }

            try {
                connection = (HttpsURLConnection) queryUrl.openConnection();
                connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
                connection.setRequestProperty("User-Agent", Settings.APP_NAME);

                if (needAuth) {
                    connection.setRequestProperty("Key", keys.getApiKey());
                    connection.setRequestProperty("Sign",
                            TradeUtils.signRequest(keys.getPrivateKey(), post_data, SIGN_HASH_FUNCTION, ENCODING));
                }

                connection.setDoOutput(true);
                connection.setDoInput(true);

                if (isGet) {
                    connection.setRequestMethod("GET");
                } else {
                    connection.setRequestMethod("POST");
                    DataOutputStream os = new DataOutputStream(connection.getOutputStream());
                    os.writeBytes(post_data);
                    os.flush();
                    os.close();
                }
            } catch (ProtocolException pe) {
                LOG.error(pe.toString());
                return null;
            } catch (IOException io) {
                LOG.error((io.toString()));
                return null;
            }

            BufferedReader br = null;
            try {
                if (connection.getResponseCode() >= 400) {
                    httpError = true;
                    response = connection.getResponseCode();
                    br = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                } else {
                    answer = "";
                    br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                }
            } catch (IOException io) {
                LOG.error(io.toString());
                return null;
            }

            if (httpError) {
                LOG.error("Query to : " + url + " (method = " + method + " )" + "\nData : \" + post_data"
                        + "\nHTTP Response : " + Objects.toString(response));
            }

            try {
                while ((output = br.readLine()) != null) {
                    answer += output;
                }
            } catch (IOException io) {
                LOG.error(io.toString());
                return null;
            }

            connection.disconnect();
            connection = null;

            return answer;
        }

    }
}