use of org.opendatakit.httpclientandroidlib.Header in project collect by opendatakit.
the class WebUtils method getXmlDocument.
/**
* Common method for returning a parsed xml document given a url and the
* http context and client objects involved in the web connection.
*/
public static DocumentFetchResult getXmlDocument(String urlString, HttpContext localContext, HttpClient httpclient) {
URI u;
try {
URL url = new URL(urlString);
u = url.toURI();
} catch (URISyntaxException | MalformedURLException e) {
Timber.i(e, "Error converting URL %s to uri", urlString);
return new DocumentFetchResult(e.getLocalizedMessage() + // + app.getString(R.string.while_accessing) + urlString);
("while accessing") + urlString, 0);
}
if (u.getHost() == null) {
return new DocumentFetchResult("Invalid server URL (no hostname): " + urlString, 0);
}
// if https then enable preemptive basic auth...
if (u.getScheme().equals("https")) {
enablePreemptiveBasicAuth(localContext, u.getHost());
}
// set up request...
HttpGet req = WebUtils.createOpenRosaHttpGet(u);
req.addHeader(WebUtils.ACCEPT_ENCODING_HEADER, WebUtils.GZIP_CONTENT_ENCODING);
HttpResponse response;
try {
response = httpclient.execute(req, localContext);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
if (statusCode != HttpStatus.SC_OK) {
WebUtils.discardEntityBytes(response);
if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
// clear the cookies -- should not be necessary?
Collect.getInstance().getCookieStore().clear();
}
String webError = response.getStatusLine().getReasonPhrase() + " (" + statusCode + ")";
return new DocumentFetchResult(u.toString() + " responded with: " + webError, statusCode);
}
if (entity == null) {
String error = "No entity body returned from: " + u.toString();
Timber.e(error);
return new DocumentFetchResult(error, 0);
}
if (!entity.getContentType().getValue().toLowerCase(Locale.ENGLISH).contains(WebUtils.HTTP_CONTENT_TYPE_TEXT_XML)) {
WebUtils.discardEntityBytes(response);
String error = "ContentType: " + entity.getContentType().getValue() + " returned from: " + u.toString() + " is not text/xml. This is often caused a network proxy. Do you need " + "to login to your network?";
Timber.e(error);
return new DocumentFetchResult(error, 0);
}
// parse response
Document doc = null;
try {
InputStream is = null;
InputStreamReader isr = null;
try {
is = entity.getContent();
Header contentEncoding = entity.getContentEncoding();
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase(WebUtils.GZIP_CONTENT_ENCODING)) {
is = new GZIPInputStream(is);
}
isr = new InputStreamReader(is, "UTF-8");
doc = new Document();
KXmlParser parser = new KXmlParser();
parser.setInput(isr);
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
doc.parse(parser);
isr.close();
isr = null;
} finally {
if (isr != null) {
try {
// ensure stream is consumed...
final long count = 1024L;
while (isr.skip(count) == count) {
// skipping to the end of the http entity
}
} catch (Exception e) {
// no-op
Timber.e(e);
}
try {
isr.close();
} catch (IOException e) {
// no-op
Timber.e(e, "Error closing input stream reader");
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
Timber.e(e, "Error closing inputstream");
// no-op
}
}
}
} catch (Exception e) {
String error = "Parsing failed with " + e.getMessage() + "while accessing " + u.toString();
Timber.e(error);
return new DocumentFetchResult(error, 0);
}
boolean isOR = false;
Header[] fields = response.getHeaders(WebUtils.OPEN_ROSA_VERSION_HEADER);
if (fields != null && fields.length >= 1) {
isOR = true;
boolean versionMatch = false;
boolean first = true;
StringBuilder b = new StringBuilder();
for (Header h : fields) {
if (WebUtils.OPEN_ROSA_VERSION.equals(h.getValue())) {
versionMatch = true;
break;
}
if (!first) {
b.append("; ");
}
first = false;
b.append(h.getValue());
}
if (!versionMatch) {
Timber.w("%s unrecognized version(s): %s", WebUtils.OPEN_ROSA_VERSION_HEADER, b.toString());
}
}
return new DocumentFetchResult(doc, isOR);
} catch (Exception e) {
String cause;
Throwable c = e;
while (c.getCause() != null) {
c = c.getCause();
}
cause = c.toString();
String error = "Error: " + cause + " while accessing " + u.toString();
Timber.w(error);
return new DocumentFetchResult(error, 0);
}
}
use of org.opendatakit.httpclientandroidlib.Header in project collect by opendatakit.
the class DownloadFormsTask method downloadFile.
/**
* Common routine to download a document from the downloadUrl and save the contents in the file
* 'file'. Shared by media file download and form file download.
* <p>
* SurveyCTO: The file is saved into a temp folder and is moved to the final place if everything
* is okay, so that garbage is not left over on cancel.
*
* @param file the final file
* @param downloadUrl the url to get the contents from.
*/
private void downloadFile(File file, String downloadUrl) throws IOException, TaskCancelledException, URISyntaxException, Exception {
File tempFile = File.createTempFile(file.getName(), TEMP_DOWNLOAD_EXTENSION, new File(Collect.CACHE_PATH));
URI uri;
try {
// assume the downloadUrl is escaped properly
URL url = new URL(downloadUrl);
uri = url.toURI();
} catch (MalformedURLException | URISyntaxException e) {
Timber.e(e, "Unable to get a URI for download URL : %s due to %s : ", downloadUrl, e.getMessage());
throw e;
}
// WiFi network connections can be renegotiated during a large form download sequence.
// This will cause intermittent download failures. Silently retry once after each
// failure. Only if there are two consecutive failures do we abort.
boolean success = false;
int attemptCount = 0;
final int MAX_ATTEMPT_COUNT = 2;
while (!success && ++attemptCount <= MAX_ATTEMPT_COUNT) {
if (isCancelled()) {
throw new TaskCancelledException(tempFile);
}
Timber.i("Started downloading to %s from %s", tempFile.getAbsolutePath(), downloadUrl);
// get shared HttpContext so that authentication and cookies are retained.
HttpContext localContext = Collect.getInstance().getHttpContext();
HttpClient httpclient = WebUtils.createHttpClient(WebUtils.CONNECTION_TIMEOUT);
// set up request...
HttpGet req = WebUtils.createOpenRosaHttpGet(uri);
req.addHeader(WebUtils.ACCEPT_ENCODING_HEADER, WebUtils.GZIP_CONTENT_ENCODING);
HttpResponse response;
try {
response = httpclient.execute(req, localContext);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
WebUtils.discardEntityBytes(response);
if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
// clear the cookies -- should not be necessary?
Collect.getInstance().getCookieStore().clear();
}
String errMsg = Collect.getInstance().getString(R.string.file_fetch_failed, downloadUrl, response.getStatusLine().getReasonPhrase(), String.valueOf(statusCode));
Timber.e(errMsg);
throw new Exception(errMsg);
}
// write connection to file
InputStream is = null;
OutputStream os = null;
try {
HttpEntity entity = response.getEntity();
is = entity.getContent();
Header contentEncoding = entity.getContentEncoding();
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase(WebUtils.GZIP_CONTENT_ENCODING)) {
is = new GZIPInputStream(is);
}
os = new FileOutputStream(tempFile);
byte[] buf = new byte[4096];
int len;
while ((len = is.read(buf)) > 0 && !isCancelled()) {
os.write(buf, 0, len);
}
os.flush();
success = true;
} finally {
if (os != null) {
try {
os.close();
} catch (Exception e) {
Timber.e(e);
}
}
if (is != null) {
try {
// ensure stream is consumed...
final long count = 1024L;
while (is.skip(count) == count) {
// skipping to the end of the http entity
}
} catch (Exception e) {
// no-op
}
try {
is.close();
} catch (Exception e) {
Timber.e(e);
}
}
}
} catch (Exception e) {
Timber.e(e.toString());
// silently retry unless this is the last attempt,
// in which case we rethrow the exception.
FileUtils.deleteAndReport(tempFile);
if (attemptCount == MAX_ATTEMPT_COUNT) {
throw e;
}
}
if (isCancelled()) {
FileUtils.deleteAndReport(tempFile);
throw new TaskCancelledException(tempFile);
}
}
Timber.d("Completed downloading of %s. It will be moved to the proper path...", tempFile.getAbsolutePath());
FileUtils.deleteAndReport(file);
String errorMessage = FileUtils.copyFile(tempFile, file);
if (file.exists()) {
Timber.w("Copied %s over %s", tempFile.getAbsolutePath(), file.getAbsolutePath());
FileUtils.deleteAndReport(tempFile);
} else {
String msg = Collect.getInstance().getString(R.string.fs_file_copy_error, tempFile.getAbsolutePath(), file.getAbsolutePath(), errorMessage);
Timber.w(msg);
throw new RuntimeException(msg);
}
}
Aggregations