/// <summary>Read the contents of an entity and return it as a byte array.</summary> /// <remarks>Read the contents of an entity and return it as a byte array.</remarks> /// <param name="entity">the entity to read from=</param> /// <returns> /// byte array containing the entity content. May be null if /// <see cref="Org.Apache.Http.HttpEntity.GetContent()">Org.Apache.Http.HttpEntity.GetContent() /// </see> /// is null. /// </returns> /// <exception cref="System.IO.IOException">if an error occurs reading the input stream /// </exception> /// <exception cref="System.ArgumentException">if entity is null or if content length > Integer.MAX_VALUE /// </exception> public static byte[] ToByteArray(HttpEntity entity) { Args.NotNull(entity, "Entity"); InputStream instream = entity.GetContent(); if (instream == null) { return(null); } try { Args.Check(entity.GetContentLength() <= int.MaxValue, "HTTP entity too large to be buffered in memory" ); int i = (int)entity.GetContentLength(); if (i < 0) { i = 4096; } ByteArrayBuffer buffer = new ByteArrayBuffer(i); byte[] tmp = new byte[4096]; int l; while ((l = instream.Read(tmp)) != -1) { buffer.Append(tmp, 0, l); } return(buffer.ToByteArray()); } finally { instream.Close(); } }
/// <summary> /// Get the entity content as a String, using the provided default character set /// if none is found in the entity. /// </summary> /// <remarks> /// Get the entity content as a String, using the provided default character set /// if none is found in the entity. /// If defaultCharset is null, the default "ISO-8859-1" is used. /// </remarks> /// <param name="entity">must not be null</param> /// <param name="defaultCharset">character set to be applied if none found in the entity /// </param> /// <returns> /// the entity content as a String. May be null if /// <see cref="Org.Apache.Http.HttpEntity.GetContent()">Org.Apache.Http.HttpEntity.GetContent() /// </see> /// is null. /// </returns> /// <exception cref="Org.Apache.Http.ParseException">if header elements cannot be parsed /// </exception> /// <exception cref="System.ArgumentException">if entity is null or if content length > Integer.MAX_VALUE /// </exception> /// <exception cref="System.IO.IOException">if an error occurs reading the input stream /// </exception> /// <exception cref="Sharpen.UnsupportedCharsetException"> /// Thrown when the named charset is not available in /// this instance of the Java virtual machine /// </exception> public static string ToString(HttpEntity entity, Encoding defaultCharset) { Args.NotNull(entity, "Entity"); InputStream instream = entity.GetContent(); if (instream == null) { return(null); } try { Args.Check(entity.GetContentLength() <= int.MaxValue, "HTTP entity too large to be buffered in memory" ); int i = (int)entity.GetContentLength(); if (i < 0) { i = 4096; } Encoding charset = null; try { ContentType contentType = ContentType.Get(entity); if (contentType != null) { charset = contentType.GetCharset(); } } catch (UnsupportedCharsetException ex) { throw new UnsupportedEncodingException(ex.Message); } if (charset == null) { charset = defaultCharset; } if (charset == null) { charset = HTTP.DefContentCharset; } StreamReader reader = new InputStreamReader(instream, charset); CharArrayBuffer buffer = new CharArrayBuffer(i); char[] tmp = new char[1024]; int l; while ((l = reader.Read(tmp)) != -1) { buffer.Append(tmp, 0, l); } return(buffer.ToString()); } finally { instream.Close(); } }
/// <summary> /// Ensures that the entity content is fully consumed and the content stream, if exists, /// is closed. /// </summary> /// <remarks> /// Ensures that the entity content is fully consumed and the content stream, if exists, /// is closed. /// </remarks> /// <param name="entity">the entity to consume.</param> /// <exception cref="System.IO.IOException">if an error occurs reading the input stream /// </exception> /// <since>4.1</since> public static void Consume(HttpEntity entity) { if (entity == null) { return; } if (entity.IsStreaming()) { InputStream instream = entity.GetContent(); if (instream != null) { instream.Close(); } } }
public virtual void Run() { running = true; HttpClient httpClient; if (client == null) { // This is a race condition that can be reproduced by calling cbpuller.start() and cbpuller.stop() // directly afterwards. What happens is that by the time the Changetracker thread fires up, // the cbpuller has already set this.client to null. See issue #109 Log.W(Database.Tag, "ChangeTracker run() loop aborting because client == null"); return; } if (mode == ChangeTracker.ChangeTrackerMode.Continuous) { // there is a failing unit test for this, and from looking at the code the Replication // object will never use Continuous mode anyway. Explicitly prevent its use until // it is demonstrated to actually work. throw new RuntimeException("ChangeTracker does not correctly support continuous mode" ); } httpClient = client.GetHttpClient(); ChangeTrackerBackoff backoff = new ChangeTrackerBackoff(); while (running) { Uri url = GetChangesFeedURL(); request = new HttpRequestMessage(url.ToString()); AddRequestHeaders(request); // if the URL contains user info AND if this a DefaultHttpClient // then preemptively set the auth credentials if (url.GetUserInfo() != null) { Log.V(Database.Tag, "url.getUserInfo(): " + url.GetUserInfo()); if (url.GetUserInfo().Contains(":") && !url.GetUserInfo().Trim().Equals(":")) { string[] userInfoSplit = url.GetUserInfo().Split(":"); throw new NotImplementedException(); // Credentials creds = new UsernamePasswordCredentials(URIUtils.Decode(userInfoSplit // [0]), URIUtils.Decode(userInfoSplit[1])); // if (httpClient is DefaultHttpClient) // { // DefaultHttpClient dhc = (DefaultHttpClient)httpClient; // MessageProcessingHandler preemptiveAuth = new _MessageProcessingHandler_212(creds // ); // dhc.AddRequestInterceptor((HttpWebRequest request, HttpContext context)=> // { // AuthState authState = (AuthState)context.GetAttribute(ClientContext.TargetAuthState // ); // CredentialsProvider credsProvider = (CredentialsProvider)context.GetAttribute(ClientContext // .CredsProvider); // HttpHost targetHost = (HttpHost)context.GetAttribute(ExecutionContext.HttpTargetHost // ); // if (authState.GetAuthScheme() == null) // { // AuthScope authScope = new AuthScope(targetHost.GetHostName(), targetHost.GetPort( // )); // authState.SetAuthScheme(new BasicScheme()); // authState.SetCredentials(creds); // } // }, 0); // } } else { Log.W(Database.Tag, "ChangeTracker Unable to parse user info, not setting credentials" ); } } try { string maskedRemoteWithoutCredentials = GetChangesFeedURL().ToString(); maskedRemoteWithoutCredentials = maskedRemoteWithoutCredentials.ReplaceAll("://.*:.*@" , "://---:---@"); Log.V(Database.Tag, "Making request to " + maskedRemoteWithoutCredentials); HttpResponse response = httpClient.Execute(request); StatusLine status = response.GetStatusLine(); if (status.GetStatusCode() >= 300) { Log.E(Database.Tag, "Change tracker got error " + Sharpen.Extensions.ToString(status .GetStatusCode())); string msg = string.Format(status.ToString()); this.error = new CouchbaseLiteException(msg, new Status(status.GetStatusCode())); Stop(); } HttpEntity entity = response.GetEntity(); InputStream input = null; if (entity != null) { input = entity.GetContent(); if (mode == ChangeTracker.ChangeTrackerMode.LongPoll) { IDictionary <string, object> fullBody = Manager.GetObjectMapper().ReadValue <IDictionary >(input); bool responseOK = ReceivedPollResponse(fullBody); if (mode == ChangeTracker.ChangeTrackerMode.LongPoll && responseOK) { Log.V(Database.Tag, "Starting new longpoll"); continue; } else { Log.W(Database.Tag, "Change tracker calling stop"); Stop(); } } else { JsonFactory jsonFactory = Manager.GetObjectMapper().GetJsonFactory(); JsonParser jp = jsonFactory.CreateJsonParser(input); while (jp.CurrentToken() != JsonToken.StartArray) { } // ignore these tokens while (jp.CurrentToken() == JsonToken.StartObject) { IDictionary <string, object> change = (IDictionary)Manager.GetObjectMapper().ReadValue <IDictionary>(jp); if (!ReceivedChange(change)) { Log.W(Database.Tag, string.Format("Received unparseable change line from server: %s" , change)); } } Stop(); break; } backoff.ResetBackoff(); } } catch (Exception e) { if (!running && e is IOException) { } else { // in this case, just silently absorb the exception because it // frequently happens when we're shutting down and have to // close the socket underneath our read. Log.E(Database.Tag, "Exception in change tracker", e); } backoff.SleepAppropriateAmountOfTime(); } } Log.V(Database.Tag, "Change tracker run loop exiting"); }
protected internal override void ExecuteRequest(HttpClient httpClient, HttpRequestMessage request) { object fullBody = null; Exception error = null; HttpResponse response = null; try { if (request.IsAborted()) { RespondWithResult(fullBody, new Exception(string.Format("%s: Request %s has been aborted" , this, request)), response); return; } response = httpClient.Execute(request); try { // add in cookies to global store if (httpClient is DefaultHttpClient) { DefaultHttpClient defaultHttpClient = (DefaultHttpClient)httpClient; clientFactory.AddCookies(defaultHttpClient.GetCookieStore().GetCookies()); } } catch (Exception e) { Log.E(Log.TagRemoteRequest, "Unable to add in cookies to global store", e); } StatusLine status = response.GetStatusLine(); if (status.GetStatusCode() >= 300) { Log.E(Log.TagRemoteRequest, "Got error status: %d for %s. Reason: %s", status.GetStatusCode (), request, status.GetReasonPhrase()); error = new HttpResponseException(status.GetStatusCode(), status.GetReasonPhrase( )); } else { HttpEntity entity = response.GetEntity(); Header contentTypeHeader = entity.GetContentType(); InputStream inputStream = null; if (contentTypeHeader != null && contentTypeHeader.GetValue().Contains("multipart/" )) { Log.V(Log.TagSync, "contentTypeHeader = %s", contentTypeHeader.GetValue()); try { _topReader = new MultipartReader(contentTypeHeader.GetValue(), this); inputStream = entity.GetContent(); int bufLen = 1024; byte[] buffer = new byte[bufLen]; int numBytesRead = 0; while ((numBytesRead = inputStream.Read(buffer)) != -1) { if (numBytesRead != bufLen) { byte[] bufferToAppend = Arrays.CopyOfRange(buffer, 0, numBytesRead); _topReader.AppendData(bufferToAppend); } else { _topReader.AppendData(buffer); } } _topReader.Finished(); RespondWithResult(fullBody, error, response); } finally { try { inputStream.Close(); } catch (IOException) { } } } else { Log.V(Log.TagSync, "contentTypeHeader is not multipart = %s", contentTypeHeader.GetValue ()); if (entity != null) { try { inputStream = entity.GetContent(); fullBody = Manager.GetObjectMapper().ReadValue <object>(inputStream); RespondWithResult(fullBody, error, response); } finally { try { inputStream.Close(); } catch (IOException) { } } } } } } catch (IOException e) { Log.E(Log.TagRemoteRequest, "io exception", e); error = e; RespondWithResult(fullBody, e, response); } catch (Exception e) { Log.E(Log.TagRemoteRequest, "%s: executeRequest() Exception: ", e, this); error = e; RespondWithResult(fullBody, e, response); } }
protected internal override void ExecuteRequest(HttpClient httpClient, HttpRequestMessage request) { object fullBody = null; Exception error = null; try { HttpResponse response = httpClient.Execute(request); try { // add in cookies to global store if (httpClient is DefaultHttpClient) { DefaultHttpClient defaultHttpClient = (DefaultHttpClient)httpClient; CouchbaseLiteHttpClientFactory.Instance.AddCookies(defaultHttpClient.GetCookieStore ().GetCookies()); } } catch (Exception e) { Log.E(Database.Tag, "Unable to add in cookies to global store", e); } StatusLine status = response.GetStatusLine(); if (status.GetStatusCode() >= 300) { Log.E(Database.Tag, "Got error " + Sharpen.Extensions.ToString(status.GetStatusCode ())); Log.E(Database.Tag, "Request was for: " + request.ToString()); Log.E(Database.Tag, "Status reason: " + status.GetReasonPhrase()); error = new HttpResponseException(status.GetStatusCode(), status.GetReasonPhrase( )); } else { HttpEntity entity = response.GetEntity(); Header contentTypeHeader = entity.GetContentType(); InputStream inputStream = null; if (contentTypeHeader != null && contentTypeHeader.GetValue().Contains("multipart/related" )) { try { MultipartDocumentReader reader = new MultipartDocumentReader(response, db); reader.SetContentType(contentTypeHeader.GetValue()); inputStream = entity.GetContent(); int bufLen = 1024; byte[] buffer = new byte[bufLen]; int numBytesRead = 0; while ((numBytesRead = inputStream.Read(buffer)) != -1) { if (numBytesRead != bufLen) { byte[] bufferToAppend = Arrays.CopyOfRange(buffer, 0, numBytesRead); reader.AppendData(bufferToAppend); } else { reader.AppendData(buffer); } } reader.Finish(); fullBody = reader.GetDocumentProperties(); RespondWithResult(fullBody, error); } finally { try { inputStream.Close(); } catch (IOException) { } } } else { if (entity != null) { try { inputStream = entity.GetContent(); fullBody = Manager.GetObjectMapper().ReadValue <object>(inputStream); RespondWithResult(fullBody, error); } finally { try { inputStream.Close(); } catch (IOException) { } } } } } } catch (ClientProtocolException e) { Log.E(Database.Tag, "client protocol exception", e); error = e; } catch (IOException e) { Log.E(Database.Tag, "io exception", e); error = e; } }
public virtual void Run() { running = true; HttpClient httpClient; if (client == null) { // This is a race condition that can be reproduced by calling cbpuller.start() and cbpuller.stop() // directly afterwards. What happens is that by the time the Changetracker thread fires up, // the cbpuller has already set this.client to null. See issue #109 Log.W(Log.TagChangeTracker, "%s: ChangeTracker run() loop aborting because client == null" , this); return; } if (mode == ChangeTracker.ChangeTrackerMode.Continuous) { // there is a failing unit test for this, and from looking at the code the Replication // object will never use Continuous mode anyway. Explicitly prevent its use until // it is demonstrated to actually work. throw new RuntimeException("ChangeTracker does not correctly support continuous mode" ); } httpClient = client.GetHttpClient(); backoff = new ChangeTrackerBackoff(); while (running) { Uri url = GetChangesFeedURL(); if (usePOST) { HttpPost postRequest = new HttpPost(url.ToString()); postRequest.SetHeader("Content-Type", "application/json"); StringEntity entity; try { entity = new StringEntity(ChangesFeedPOSTBody()); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } postRequest.SetEntity(entity); request = postRequest; } else { request = new HttpGet(url.ToString()); } AddRequestHeaders(request); // Perform BASIC Authentication if needed bool isUrlBasedUserInfo = false; // If the URL contains user info AND if this a DefaultHttpClient then preemptively set the auth credentials string userInfo = url.GetUserInfo(); if (userInfo != null) { isUrlBasedUserInfo = true; } else { if (authenticator != null) { AuthenticatorImpl auth = (AuthenticatorImpl)authenticator; userInfo = auth.AuthUserInfo(); } } if (userInfo != null) { if (userInfo.Contains(":") && !userInfo.Trim().Equals(":")) { string[] userInfoElements = userInfo.Split(":"); string username = isUrlBasedUserInfo ? URIUtils.Decode(userInfoElements[0]) : userInfoElements [0]; string password = isUrlBasedUserInfo ? URIUtils.Decode(userInfoElements[1]) : userInfoElements [1]; Credentials credentials = new UsernamePasswordCredentials(username, password); if (httpClient is DefaultHttpClient) { DefaultHttpClient dhc = (DefaultHttpClient)httpClient; MessageProcessingHandler preemptiveAuth = new _MessageProcessingHandler_285(credentials ); dhc.AddRequestInterceptor(preemptiveAuth, 0); } } else { Log.W(Log.TagChangeTracker, "RemoteRequest Unable to parse user info, not setting credentials" ); } } try { string maskedRemoteWithoutCredentials = GetChangesFeedURL().ToString(); maskedRemoteWithoutCredentials = maskedRemoteWithoutCredentials.ReplaceAll("://.*:.*@" , "://---:---@"); Log.V(Log.TagChangeTracker, "%s: Making request to %s", this, maskedRemoteWithoutCredentials ); HttpResponse response = httpClient.Execute(request); StatusLine status = response.GetStatusLine(); if (status.GetStatusCode() >= 300 && !Utils.IsTransientError(status)) { Log.E(Log.TagChangeTracker, "%s: Change tracker got error %d", this, status.GetStatusCode ()); this.error = new HttpResponseException(status.GetStatusCode(), status.GetReasonPhrase ()); Stop(); } HttpEntity entity = response.GetEntity(); InputStream input = null; if (entity != null) { try { input = entity.GetContent(); if (mode == ChangeTracker.ChangeTrackerMode.LongPoll) { // continuous replications IDictionary <string, object> fullBody = Manager.GetObjectMapper().ReadValue <IDictionary >(input); bool responseOK = ReceivedPollResponse(fullBody); if (mode == ChangeTracker.ChangeTrackerMode.LongPoll && responseOK) { Log.V(Log.TagChangeTracker, "%s: Starting new longpoll", this); backoff.ResetBackoff(); continue; } else { Log.W(Log.TagChangeTracker, "%s: Change tracker calling stop (LongPoll)", this); Stop(); } } else { // one-shot replications JsonFactory jsonFactory = Manager.GetObjectMapper().GetJsonFactory(); JsonParser jp = jsonFactory.CreateJsonParser(input); while (jp.NextToken() != JsonToken.StartArray) { } // ignore these tokens while (jp.NextToken() == JsonToken.StartObject) { IDictionary <string, object> change = (IDictionary)Manager.GetObjectMapper().ReadValue <IDictionary>(jp); if (!ReceivedChange(change)) { Log.W(Log.TagChangeTracker, "Received unparseable change line from server: %s", change ); } } Log.W(Log.TagChangeTracker, "%s: Change tracker calling stop (OneShot)", this); Stop(); break; } backoff.ResetBackoff(); } finally { try { entity.ConsumeContent(); } catch (IOException) { } } } } catch (Exception e) { if (!running && e is IOException) { } else { // in this case, just silently absorb the exception because it // frequently happens when we're shutting down and have to // close the socket underneath our read. Log.E(Log.TagChangeTracker, this + ": Exception in change tracker", e); } backoff.SleepAppropriateAmountOfTime(); } } Log.V(Log.TagChangeTracker, "%s: Change tracker run loop exiting", this); }
protected internal virtual void ExecuteRequest(HttpClient httpClient, HttpRequestMessage request) { object fullBody = null; Exception error = null; try { HttpResponse response = httpClient.Execute(request); // add in cookies to global store try { if (httpClient is DefaultHttpClient) { DefaultHttpClient defaultHttpClient = (DefaultHttpClient)httpClient; CouchbaseLiteHttpClientFactory.Instance.AddCookies(defaultHttpClient.GetCookieStore ().GetCookies()); } } catch (Exception e) { Log.E(Database.Tag, "Unable to add in cookies to global store", e); } StatusLine status = response.GetStatusLine(); if (status.GetStatusCode() >= 300) { Log.E(Database.Tag, "Got error " + Sharpen.Extensions.ToString(status.GetStatusCode ())); Log.E(Database.Tag, "Request was for: " + request.ToString()); Log.E(Database.Tag, "Status reason: " + status.GetReasonPhrase()); error = new HttpResponseException(status.GetStatusCode(), status.GetReasonPhrase( )); } else { HttpEntity temp = response.GetEntity(); if (temp != null) { InputStream stream = null; try { stream = temp.GetContent(); fullBody = Manager.GetObjectMapper().ReadValue <object>(stream); } finally { try { stream.Close(); } catch (IOException) { } } } } } catch (ClientProtocolException e) { Log.E(Database.Tag, "client protocol exception", e); error = e; } catch (IOException e) { Log.E(Database.Tag, "io exception", e); error = e; } RespondWithResult(fullBody, error); }
/// <exception cref="System.IO.IOException"></exception> public virtual InputStream GetContent() { return(wrappedEntity.GetContent()); }
protected internal virtual void ExecuteRequest(HttpClient httpClient, HttpRequestMessage request) { object fullBody = null; Exception error = null; HttpResponse response = null; try { Log.V(Log.TagSync, "%s: RemoteRequest executeRequest() called, url: %s", this, url ); if (request.IsAborted()) { Log.V(Log.TagSync, "%s: RemoteRequest has already been aborted", this); RespondWithResult(fullBody, new Exception(string.Format("%s: Request %s has been aborted" , this, request)), response); return; } Log.V(Log.TagSync, "%s: RemoteRequest calling httpClient.execute", this); response = httpClient.Execute(request); Log.V(Log.TagSync, "%s: RemoteRequest called httpClient.execute", this); // add in cookies to global store try { if (httpClient is DefaultHttpClient) { DefaultHttpClient defaultHttpClient = (DefaultHttpClient)httpClient; this.clientFactory.AddCookies(defaultHttpClient.GetCookieStore().GetCookies()); } } catch (Exception e) { Log.E(Log.TagRemoteRequest, "Unable to add in cookies to global store", e); } StatusLine status = response.GetStatusLine(); if (Utils.IsTransientError(status) && RetryRequest()) { return; } if (status.GetStatusCode() >= 300) { Log.E(Log.TagRemoteRequest, "Got error status: %d for %s. Reason: %s", status.GetStatusCode (), request, status.GetReasonPhrase()); error = new HttpResponseException(status.GetStatusCode(), status.GetReasonPhrase( )); } else { HttpEntity temp = response.GetEntity(); if (temp != null) { InputStream stream = null; try { stream = temp.GetContent(); fullBody = Manager.GetObjectMapper().ReadValue <object>(stream); } finally { try { stream.Close(); } catch (IOException) { } } } } } catch (IOException e) { Log.E(Log.TagRemoteRequest, "io exception", e); error = e; // Treat all IOExceptions as transient, per: // http://hc.apache.org/httpclient-3.x/exception-handling.html Log.V(Log.TagSync, "%s: RemoteRequest calling retryRequest()", this); if (RetryRequest()) { return; } } catch (Exception e) { Log.E(Log.TagRemoteRequest, "%s: executeRequest() Exception: ", e, this); error = e; } Log.V(Log.TagSync, "%s: RemoteRequest calling respondWithResult. error: %s", this , error); RespondWithResult(fullBody, error, response); }