String[] extraFieldValues, String[] acceptableTypes,
boolean sendAcceptableTypes, boolean allowNoMediaType,
OutputStream output, String[] encoding, int invalidURLCode,
int serverNotFoundCode, int resourceNotFoundCode,
int invalidMediaTypeCode) throws IOException {
Connection conn = null;
StringBuffer acceptField;
int responseCode;
String retryAfterField;
int retryInterval;
String mediaType;
try {
for (; ; ) {
try {
conn = Connector.open(url, Connector.READ);
} catch (IllegalArgumentException e) {
throw new InvalidJadException(invalidURLCode, url);
} catch (ConnectionNotFoundException e) {
// protocol not found
throw new InvalidJadException(invalidURLCode, url);
}
if (!(conn instanceof HttpConnection)) {
// only HTTP or HTTPS are supported
throw new InvalidJadException(invalidURLCode, url);
}
httpConnection = (HttpConnection)conn;
if (extraFieldKeys != null) {
for (int i = 0; i < extraFieldKeys.length &&
extraFieldKeys[i] != null; i++) {
httpConnection.setRequestProperty(extraFieldKeys[i],
extraFieldValues[i]);
}
}
// 256 is given to avoid resizing without adding lengths
acceptField = new StringBuffer(256);
if (sendAcceptableTypes) {
// there must be one or more acceptable media types
acceptField.append(acceptableTypes[0]);
for (int i = 1; i < acceptableTypes.length; i++) {
acceptField.append(", ");
acceptField.append(acceptableTypes[i]);
}
} else {
/* Send at least a wildcard to satisfy WAP gateways. */
acceptField.append("*/*");
}
httpConnection.setRequestProperty("Accept",
acceptField.toString());
httpConnection.setRequestMethod(HttpConnection.GET);
if (state.username != null &&
state.password != null) {
httpConnection.setRequestProperty("Authorization",
formatAuthCredentials(state.username,
state.password));
}
if (state.proxyUsername != null &&
state.proxyPassword != null) {
httpConnection.setRequestProperty("Proxy-Authorization",
formatAuthCredentials(state.proxyUsername,
state.proxyPassword));
}
try {
responseCode = httpConnection.getResponseCode();
} catch (IOException ioe) {
if (httpConnection.getHost() == null) {
throw new InvalidJadException(invalidURLCode, url);
}
throw new InvalidJadException(serverNotFoundCode, url);
}
if (responseCode != HttpConnection.HTTP_UNAVAILABLE) {
break;
}
retryAfterField = httpConnection.getHeaderField("Retry-After");
if (retryAfterField == null) {
break;
}
try {
/*
* see if the retry interval is in seconds, and
* not an absolute date
*/
retryInterval = Integer.parseInt(retryAfterField);
if (retryInterval > 0) {
if (retryInterval > 60) {
// only wait 1 min
retryInterval = 60;
}
Thread.sleep(retryInterval * 1000);
}
} catch (InterruptedException ie) {
// ignore thread interrupt
break;
} catch (NumberFormatException ne) {
// ignore bad format
break;
}
httpConnection.close();
if (state.stopInstallation) {
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
}
} // end for
if (responseCode == HttpConnection.HTTP_NOT_FOUND) {
throw new InvalidJadException(resourceNotFoundCode);
}
if (responseCode == HttpConnection.HTTP_NOT_ACCEPTABLE) {
throw new InvalidJadException(invalidMediaTypeCode, "");
}
if (responseCode == HttpConnection.HTTP_UNAUTHORIZED) {
// automatically throws the correct exception
checkIfBasicAuthSupported(
httpConnection.getHeaderField("WWW-Authenticate"));
state.exception =
new InvalidJadException(InvalidJadException.UNAUTHORIZED);
return 0;
}
if (responseCode == HttpConnection.HTTP_PROXY_AUTH) {
// automatically throws the correct exception
checkIfBasicAuthSupported(
httpConnection.getHeaderField("WWW-Authenticate"));
state.exception =
new InvalidJadException(InvalidJadException.PROXY_AUTH);
return 0;
}
if (responseCode != HttpConnection.HTTP_OK) {
throw new IOException("Failed to download " + url +
" HTTP response code: " + responseCode);
}
mediaType = Util.getHttpMediaType(httpConnection.getType());
if (mediaType != null) {
boolean goodType = false;
for (int i = 0; i < acceptableTypes.length; i++) {
if (mediaType.equals(acceptableTypes[i])) {
goodType = true;
break;
}
}
if (!goodType) {
throw new InvalidJadException(invalidMediaTypeCode,
mediaType);
}
} else if (!allowNoMediaType) {
throw new InvalidJadException(invalidMediaTypeCode, "");
}
if (encoding != null) {
encoding[0] = getCharset(httpConnection.getType());
}
httpInputStream = httpConnection.openInputStream();
return transferData(httpInputStream, output, MAX_DL_SIZE);
} finally {
// Close the streams or connections this method opened.
try {
httpInputStream.close();
} catch (Exception e) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"stream close threw an Exception");
}
}
try {
conn.close();
} catch (Exception e) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"connection close threw an Exception");
}