|
|
|
@@ -899,13 +899,74 @@ public class JuceAppActivity extends Activity |
|
|
|
//==============================================================================
|
|
|
|
public static class HTTPStream
|
|
|
|
{
|
|
|
|
public HTTPStream (HttpURLConnection connection_,
|
|
|
|
int[] statusCode_,
|
|
|
|
StringBuffer responseHeaders_)
|
|
|
|
public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse,
|
|
|
|
String headersToUse, int timeOutMsToUse,
|
|
|
|
int[] statusCodeToUse, StringBuffer responseHeadersToUse,
|
|
|
|
int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException
|
|
|
|
{
|
|
|
|
connection = connection_;
|
|
|
|
statusCode = statusCode_;
|
|
|
|
responseHeaders = responseHeaders_;
|
|
|
|
isPost = isPostToUse;
|
|
|
|
postData = postDataToUse;
|
|
|
|
headers = headersToUse;
|
|
|
|
timeOutMs = timeOutMsToUse;
|
|
|
|
statusCode = statusCodeToUse;
|
|
|
|
responseHeaders = responseHeadersToUse;
|
|
|
|
numRedirectsToFollow = numRedirectsToFollowToUse;
|
|
|
|
httpRequestCmd = httpRequestCmdToUse;
|
|
|
|
|
|
|
|
connection = createConnection (address, isPost, postData, headers, timeOutMs, httpRequestCmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
private final HttpURLConnection createConnection (String address, boolean isPost, byte[] postData,
|
|
|
|
String headers, int timeOutMs, String httpRequestCmdToUse) throws IOException
|
|
|
|
{
|
|
|
|
HttpURLConnection newConnection = (HttpURLConnection) (new URL(address).openConnection());
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
newConnection.setInstanceFollowRedirects (false);
|
|
|
|
newConnection.setConnectTimeout (timeOutMs);
|
|
|
|
newConnection.setReadTimeout (timeOutMs);
|
|
|
|
|
|
|
|
// headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines.
|
|
|
|
// So convert headers string to an array, with an element for each line
|
|
|
|
String headerLines[] = headers.split("\\n");
|
|
|
|
|
|
|
|
// Set request headers
|
|
|
|
for (int i = 0; i < headerLines.length; ++i)
|
|
|
|
{
|
|
|
|
int pos = headerLines[i].indexOf (":");
|
|
|
|
|
|
|
|
if (pos > 0 && pos < headerLines[i].length())
|
|
|
|
{
|
|
|
|
String field = headerLines[i].substring (0, pos);
|
|
|
|
String value = headerLines[i].substring (pos + 1);
|
|
|
|
|
|
|
|
if (value.length() > 0)
|
|
|
|
newConnection.setRequestProperty (field, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
newConnection.setRequestMethod (httpRequestCmd);
|
|
|
|
|
|
|
|
if (isPost)
|
|
|
|
{
|
|
|
|
newConnection.setDoOutput (true);
|
|
|
|
|
|
|
|
if (postData != null)
|
|
|
|
{
|
|
|
|
OutputStream out = newConnection.getOutputStream();
|
|
|
|
out.write(postData);
|
|
|
|
out.flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newConnection;
|
|
|
|
}
|
|
|
|
catch (Throwable e)
|
|
|
|
{
|
|
|
|
newConnection.disconnect();
|
|
|
|
throw new IOException ("Connection error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private final InputStream getCancellableStream (final boolean isInput) throws ExecutionException
|
|
|
|
@@ -928,19 +989,12 @@ public class JuceAppActivity extends Activity |
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (connection.getConnectTimeout() > 0)
|
|
|
|
return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS);
|
|
|
|
else
|
|
|
|
return streamFuture.get();
|
|
|
|
return streamFuture.get();
|
|
|
|
}
|
|
|
|
catch (InterruptedException e)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
catch (TimeoutException e)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
catch (CancellationException e)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
@@ -948,6 +1002,89 @@ public class JuceAppActivity extends Activity |
|
|
|
}
|
|
|
|
|
|
|
|
public final boolean connect()
|
|
|
|
{
|
|
|
|
boolean result = false;
|
|
|
|
int numFollowedRedirects = 0;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
result = doConnect();
|
|
|
|
|
|
|
|
if (! result)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (++numFollowedRedirects > numRedirectsToFollow)
|
|
|
|
break;
|
|
|
|
|
|
|
|
int status = statusCode[0];
|
|
|
|
|
|
|
|
if (status == 301 || status == 302 || status == 303 || status == 307)
|
|
|
|
{
|
|
|
|
// Assumes only one occurrence of "Location"
|
|
|
|
int pos1 = responseHeaders.indexOf ("Location:") + 10;
|
|
|
|
int pos2 = responseHeaders.indexOf ("\n", pos1);
|
|
|
|
|
|
|
|
if (pos2 > pos1)
|
|
|
|
{
|
|
|
|
String currentLocation = connection.getURL().toString();
|
|
|
|
String newLocation = responseHeaders.substring (pos1, pos2);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Handle newLocation whether it's absolute or relative
|
|
|
|
URL baseUrl = new URL (currentLocation);
|
|
|
|
URL newUrl = new URL (baseUrl, newLocation);
|
|
|
|
String transformedNewLocation = newUrl.toString();
|
|
|
|
|
|
|
|
if (transformedNewLocation != currentLocation)
|
|
|
|
{
|
|
|
|
// Clear responseHeaders before next iteration
|
|
|
|
responseHeaders.delete (0, responseHeaders.length());
|
|
|
|
|
|
|
|
synchronized (createStreamLock)
|
|
|
|
{
|
|
|
|
if (hasBeenCancelled.get())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
connection.disconnect();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
connection = createConnection (transformedNewLocation, isPost,
|
|
|
|
postData, headers, timeOutMs,
|
|
|
|
httpRequestCmd);
|
|
|
|
}
|
|
|
|
catch (Throwable e)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Throwable e)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
private final boolean doConnect()
|
|
|
|
{
|
|
|
|
synchronized (createStreamLock)
|
|
|
|
{
|
|
|
|
@@ -1094,9 +1231,15 @@ public class JuceAppActivity extends Activity |
|
|
|
public final boolean isExhausted() { return false; }
|
|
|
|
public final boolean setPosition (long newPos) { return false; }
|
|
|
|
|
|
|
|
private boolean isPost;
|
|
|
|
private byte[] postData;
|
|
|
|
private String headers;
|
|
|
|
private int timeOutMs;
|
|
|
|
String httpRequestCmd;
|
|
|
|
private HttpURLConnection connection;
|
|
|
|
private int[] statusCode;
|
|
|
|
private StringBuffer responseHeaders;
|
|
|
|
private int numRedirectsToFollow;
|
|
|
|
private InputStream inputStream;
|
|
|
|
private long position;
|
|
|
|
private final ReentrantLock createStreamLock = new ReentrantLock();
|
|
|
|
@@ -1118,89 +1261,15 @@ public class JuceAppActivity extends Activity |
|
|
|
else if (timeOutMs == 0)
|
|
|
|
timeOutMs = 30000;
|
|
|
|
|
|
|
|
// headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines.
|
|
|
|
// So convert headers string to an array, with an element for each line
|
|
|
|
String headerLines[] = headers.split("\\n");
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection());
|
|
|
|
|
|
|
|
if (connection != null)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
connection.setInstanceFollowRedirects (false);
|
|
|
|
connection.setConnectTimeout (timeOutMs);
|
|
|
|
connection.setReadTimeout (timeOutMs);
|
|
|
|
|
|
|
|
// Set request headers
|
|
|
|
for (int i = 0; i < headerLines.length; ++i)
|
|
|
|
{
|
|
|
|
int pos = headerLines[i].indexOf (":");
|
|
|
|
|
|
|
|
if (pos > 0 && pos < headerLines[i].length())
|
|
|
|
{
|
|
|
|
String field = headerLines[i].substring (0, pos);
|
|
|
|
String value = headerLines[i].substring (pos + 1);
|
|
|
|
|
|
|
|
if (value.length() > 0)
|
|
|
|
connection.setRequestProperty (field, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers,
|
|
|
|
timeOutMs, statusCode, responseHeaders,
|
|
|
|
numRedirectsToFollow, httpRequestCmd);
|
|
|
|
|
|
|
|
connection.setRequestMethod (httpRequestCmd);
|
|
|
|
if (isPost)
|
|
|
|
{
|
|
|
|
connection.setDoOutput (true);
|
|
|
|
|
|
|
|
if (postData != null)
|
|
|
|
{
|
|
|
|
OutputStream out = connection.getOutputStream();
|
|
|
|
out.write(postData);
|
|
|
|
out.flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders);
|
|
|
|
|
|
|
|
// Process redirect & continue as necessary
|
|
|
|
int status = statusCode[0];
|
|
|
|
|
|
|
|
if (--numRedirectsToFollow >= 0
|
|
|
|
&& (status == 301 || status == 302 || status == 303 || status == 307))
|
|
|
|
{
|
|
|
|
// Assumes only one occurrence of "Location"
|
|
|
|
int pos1 = responseHeaders.indexOf ("Location:") + 10;
|
|
|
|
int pos2 = responseHeaders.indexOf ("\n", pos1);
|
|
|
|
|
|
|
|
if (pos2 > pos1)
|
|
|
|
{
|
|
|
|
String newLocation = responseHeaders.substring(pos1, pos2);
|
|
|
|
// Handle newLocation whether it's absolute or relative
|
|
|
|
URL baseUrl = new URL (address);
|
|
|
|
URL newUrl = new URL (baseUrl, newLocation);
|
|
|
|
String transformedNewLocation = newUrl.toString();
|
|
|
|
|
|
|
|
if (transformedNewLocation != address)
|
|
|
|
{
|
|
|
|
address = transformedNewLocation;
|
|
|
|
// Clear responseHeaders before next iteration
|
|
|
|
responseHeaders.delete (0, responseHeaders.length());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return httpStream;
|
|
|
|
}
|
|
|
|
catch (Throwable e)
|
|
|
|
{
|
|
|
|
connection.disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return httpStream;
|
|
|
|
}
|
|
|
|
catch (Throwable e) {}
|
|
|
|
|
|
|
|
|