package com.badlogic.gdx.net;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.Net.HttpMethods;
import com.badlogic.gdx.Net.HttpRequest;
import com.badlogic.gdx.Net.HttpResponse;
import com.badlogic.gdx.Net.HttpResponseListener;
import com.badlogic.gdx.Net.HttpStatus;
import com.badlogic.gdx.StreamUtils;
import com.badlogic.gdx.utils.GdxRuntimeException;
/**
* Implements part of the {@link Net} API using {@link HttpURLConnection}, to be easily reused between the Android and
* Desktop backends.
*
* @author acoppes
*/
public class NetJavaImpl {
static class HttpClientResponse implements HttpResponse {
private HttpURLConnection connection;
private HttpStatus status;
private InputStream inputStream;
public HttpClientResponse(HttpURLConnection connection) throws IOException {
this.connection = connection;
this.inputStream = connection.getInputStream();
try {
this.status = new HttpStatus(connection.getResponseCode());
} catch (IOException e) {
this.status = new HttpStatus(-1);
}
}
@Override
public byte[] getResult() {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
try {
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
} catch (IOException e) {
return new byte[0];
}
return buffer.toByteArray();
}
@Override
public String getResultAsString() {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String tmp, line = "";
try {
while ((tmp = reader.readLine()) != null)
line += tmp;
reader.close();
return line;
} catch (IOException e) {
return "";
}
}
@Override
public InputStream getResultAsStream() {
return inputStream;
}
@Override
public HttpStatus getStatus() {
return status;
}
}
private final ExecutorService executorService;
public NetJavaImpl() {
executorService = Executors.newCachedThreadPool();
}
public void sendHttpRequest(final HttpRequest httpRequest, final HttpResponseListener httpResponseListener) {
if (httpRequest.getUrl() == null) {
httpResponseListener.failed(new GdxRuntimeException("can't process a HTTP request without URL set"));
return;
}
try {
final String method = httpRequest.getMethod();
URL url;
if (method.equalsIgnoreCase(HttpMethods.GET)) {
String queryString = "";
String value = httpRequest.getContent();
if (value != null && !"".equals(value))
queryString = "?" + value;
url = new URL(httpRequest.getUrl() + queryString);
} else {
url = new URL(httpRequest.getUrl());
}
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// should be enabled to upload data.
connection.setDoOutput(method.equalsIgnoreCase(HttpMethods.POST));
connection.setDoInput(true);
connection.setRequestMethod(method);
// Headers get set regardless of the method
Map<String, String> headers = httpRequest.getHeaders();
Set<String> keySet = headers.keySet();
for (String name : keySet)
connection.addRequestProperty(name, headers.get(name));
// Set Timeouts
connection.setConnectTimeout(httpRequest.getTimeOut());
connection.setReadTimeout(httpRequest.getTimeOut());
executorService.submit(new Runnable() {
@Override
public void run() {
try {
// Set the content for POST (GET has the information embedded in the URL)
if (method.equalsIgnoreCase(HttpMethods.POST)) {
// we probably need to use the content as stream here instead of using it as a string.
String contentAsString = httpRequest.getContent();
InputStream contentAsStream = httpRequest.getContentStream();
OutputStream outputStream = connection.getOutputStream();
if (contentAsString != null) {
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
writer.write(contentAsString);
writer.flush();
writer.close();
} else if (contentAsStream != null) {
StreamUtils.copyStream(contentAsStream, outputStream);
outputStream.flush();
outputStream.close();
}
}
connection.connect();
// post a runnable to sync the handler with the main thread
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
try {
httpResponseListener.handleHttpResponse(new HttpClientResponse(connection));
} catch (IOException e) {
httpResponseListener.failed(e);
} finally {
connection.disconnect();
}
}
});
} catch (final Exception e) {
// post a runnable to sync the handler with the main thread
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
connection.disconnect();
httpResponseListener.failed(e);
}
});
}
// finally {
// connection.disconnect();
// }
}
});
} catch (Exception e) {
httpResponseListener.failed(e);
return;
}
}
}