/*
* Copyright (C) 2011 4th Line GmbH, Switzerland
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fourthline.konto.server.download;
import org.seamless.util.io.IO;
import org.fourthline.konto.server.dao.CurrencyDAO;
import org.fourthline.konto.shared.entity.CurrencyPair;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
/**
* @author Christian Bauer
*/
public class YahooCurrencyDownloader extends CurrencyDownloader {
public static final String BASE_URL =
"http://download.finance.yahoo.com/d/quotes.csv?s=%1$s&f=l1";
public YahooCurrencyDownloader(CurrencyDAO currencyDAO) {
super(currencyDAO);
}
@Override
protected void updateExchangeRates(List<CurrencyPair> pairs) throws Exception {
StringBuilder sb = new StringBuilder();
for (CurrencyPair pair : pairs) {
sb.append(pair.getFromCode()).append(pair.getToCode()).append("=X");
sb.append("+");
}
if (sb.length() > 0) sb.deleteCharAt(sb.length() - 1);
URL url = new URL(String.format(BASE_URL, sb.toString()));
String ratesString = retrieveExchangeRates(url);
if (ratesString == null) {
// Shouldn't happen, it's just the ugly HTTP client API in the JDK
throw new Exception("Rates couldn't be retrieved.");
}
String[] rates = ratesString.split("\n");
for (int i = 0; i < pairs.size(); i++) {
BigDecimal exchangeRate = new BigDecimal(rates[i].trim());
CurrencyPair pair = pairs.get(i);
pair.setExchangeRate(exchangeRate);
}
}
protected String retrieveExchangeRates(URL url) throws Exception{
HttpURLConnection urlConnection = null;
InputStream inputStream;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10 * 1000);
urlConnection.setConnectTimeout(10 * 1000);
inputStream = urlConnection.getInputStream();
return readResponse(urlConnection, inputStream);
} catch (IOException ex) {
if (urlConnection == null) {
throw new Exception("Could not open URL connection: " + ex, ex);
}
try {
inputStream = urlConnection.getErrorStream();
} catch (Exception errorEx) {
throw new Exception("Could not read error stream: " + errorEx);
}
if (inputStream != null) {
// Will throw exception with status >= 300
readResponse(urlConnection, inputStream);
return null;
} else {
throw new Exception("I/O exception occurred, no error response: " + ex, ex);
}
} catch (Exception ex) {
throw new Exception("Unrecoverable exception occurred, no error response possible: " + ex, ex);
} finally {
if (urlConnection != null) {
// Release any idle persistent connection, or "indicate that we don't
// want to use this server for a while"
urlConnection.disconnect();
}
}
}
protected String readResponse(HttpURLConnection urlConnection, InputStream inputStream) throws Exception {
if (urlConnection.getResponseCode() == -1) {
throw new Exception("Did not receive valid HTTP response");
}
// Status
int statusCode = urlConnection.getResponseCode();
String statusMessage = urlConnection.getResponseMessage();
if (statusCode >= 300) {
throw new Exception("Response status was: " + statusCode + " " + statusMessage);
}
// Body
byte[] bodyBytes = null;
InputStream is = null;
try {
is = inputStream;
if (inputStream != null) bodyBytes = IO.readBytes(is);
} finally {
if (is != null)
is.close();
}
if (bodyBytes != null && bodyBytes.length > 0) {
return new String(bodyBytes, "UTF-8");
} else {
throw new Exception("Response did not contain body");
}
}
}