package chatty.util;
import chatty.Chatty;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
/**
* General URL Request that just reads the whole file into a String.
*
* @author tduva
*/
public class UrlRequest implements Runnable {
private static final Logger LOGGER = Logger.getLogger(UrlRequest.class.getName());
private static final Charset CHARSET = Charset.forName("UTF-8");
private static final int CONNECT_TIMEOUT = 10000;
private static final int READ_TIMEOUT = 10000;
private static final String VERSION = "Chatty "+Chatty.VERSION;
private String url;
private int responseCode;
private String result;
private String encoding;
/**
* Label used for debug messages, which can be set by the user.
*/
private String label = "";
/**
* Construct without URL. The URL should be set via {@link setUrl(String)}.
*/
public UrlRequest() {
}
public UrlRequest(String url) {
this.url = url;
}
/**
* Sets the URL. Should be done before running the thread.
*
* @param url The URL to request as a String
*/
public final void setUrl(String url) {
this.url = url;
}
/**
* Sets the label to be used for debug messages, for easier identification
* of what the request is used for.
*
* @param label The label to be put in front of the debug messages (a space
* is automatically added after it)
*/
public final void setLabel(String label) {
this.label = label+" ";
}
@Override
public void run() {
LOGGER.info(label+"Request: "+url);
getUrl(url);
if (result != null) {
LOGGER.info(label+"Response (" + responseCode + ", " + result.length()
+ (encoding != null ? ", " + encoding : "") + "): " + url);
}
requestResult(result, responseCode);
}
/**
* Override this to get the result of the request. The {@code result}
* contains all the text returned by the request (may be null if the request
* failed), the {@code responseCode} is the HTTP Response Code (which may be
* 0 depending on whether/how the request failed).
*
* @param result The text returned by the request, with linebreaks preserved
* @param responseCode The HTTP Response Code
*/
public void requestResult(String result, int responseCode) { }
public final String getResult() {
return result;
}
/**
* Gets the given URL and reads the result line by line.
*
* @param targetUrl
* @return
*/
private void getUrl(String targetUrl) {
HttpURLConnection connection = null;
Exception exception = null;
try {
URL url = new URL(targetUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("User-Agent", VERSION);
connection.setRequestProperty("Accept-Encoding", "gzip");
connection.setConnectTimeout(CONNECT_TIMEOUT);
connection.setReadTimeout(READ_TIMEOUT);
encoding = connection.getContentEncoding();
// Read response
InputStream input = connection.getInputStream();
if ("gzip".equals(connection.getContentEncoding())) {
input = new GZIPInputStream(input);
}
StringBuilder response = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, CHARSET))) {
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
response.append("\n");
}
}
result = response.toString();
} catch (IOException ex) {
exception = ex;
} finally {
if (connection != null) {
try {
responseCode = connection.getResponseCode();
connection.disconnect();
if (responseCode != 200) {
LOGGER.warning(label+"Request Error [" + url + "] ("+responseCode+", " + exception + ")");
}
} catch (IOException ex) {
LOGGER.warning(label+"Request Error [" + url + "] (" + exception + ")");
}
} else {
LOGGER.warning(label+"Request Error [" + url + "] (" + exception + ")");
}
}
}
}