summaryrefslogtreecommitdiffstats
path: root/mobile/android/thirdparty/ch
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /mobile/android/thirdparty/ch
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'mobile/android/thirdparty/ch')
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionClosedException.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionReuseStrategy.java70
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/Consts.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/ContentTooLongException.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/FormattedHeader.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/Header.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElement.java108
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElementIterator.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderIterator.java56
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpClientConnection.java102
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnection.java104
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionFactory.java42
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionMetrics.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntity.java199
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntityEnclosingRequest.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpException.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHeaders.java206
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHost.java290
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpInetConnection.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpMessage.java210
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequest.java53
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestFactory.java43
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestInterceptor.java68
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponse.java155
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseFactory.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseInterceptor.java68
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpServerConnection.java88
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpStatus.java175
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpVersion.java110
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/MalformedChunkCodingException.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/MessageConstraintException.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/MethodNotSupportedException.java59
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/NameValuePair.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/NoHttpResponseException.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/ParseException.java61
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolException.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolVersion.java264
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/README.txt1
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/ReasonPhraseCatalog.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/RequestLine.java49
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/StatusLine.java52
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/TokenIterator.java59
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/TruncatedChunkException.java48
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/UnsupportedHttpVersionException.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/Base64.java741
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/HttpClientAndroidLog.java113
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/GuardedBy.java76
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/Immutable.java59
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/NotThreadSafe.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/ThreadSafe.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/package-info.java34
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AUTH.java64
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthOption.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthProtocolState.java33
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScheme.java130
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeFactory.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeProvider.java46
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeRegistry.java155
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScope.java302
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthState.java235
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthenticationException.java70
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/BasicUserPrincipal.java89
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ChallengeState.java38
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ContextAwareAuthScheme.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/Credentials.java44
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/InvalidCredentialsException.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/MalformedChallengeException.java70
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTCredentials.java177
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTUserPrincipal.java113
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/UsernamePasswordCredentials.java120
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthPNames.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParamBean.java55
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParams.java82
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthCache.java49
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationHandler.java101
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationStrategy.java130
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/BackoffManager.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CircularRedirectException.java68
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ClientProtocolException.java61
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ConnectionBackoffStrategy.java64
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CookieStore.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CredentialsProvider.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpClient.java258
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpRequestRetryHandler.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpResponseException.java52
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/NonRepeatableRequestException.java72
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectException.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectHandler.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectStrategy.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RequestDirector.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ResponseHandler.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ServiceUnavailableRetryStrategy.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/UserTokenHandler.java58
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/CacheResponseStatus.java55
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HeaderConstants.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheContext.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntry.java263
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializationException.java48
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializer.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheInvalidator.java58
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheStorage.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateCallback.java52
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateException.java48
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/InputLimit.java76
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/Resource.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/ResourceFactory.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/package.html78
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/AuthSchemes.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/CookieSpecs.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/RequestConfig.java442
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DecompressingEntity.java105
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateDecompressingEntity.java96
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateInputStream.java228
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/EntityBuilder.java342
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipCompressingEntity.java113
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipDecompressingEntity.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/LazyDecompressingInputStream.java105
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/UrlEncodedFormEntity.java107
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbortableHttpRequest.java82
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbstractExecutionAwareRequest.java131
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/CloseableHttpResponse.java40
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/Configurable.java44
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpDelete.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java76
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpExecutionAware.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpGet.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpHead.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpOptions.java100
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPatch.java75
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPost.java84
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPut.java76
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestBase.java124
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestWrapper.java171
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpTrace.java79
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpUriRequest.java84
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/RequestBuilder.java351
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AllClientPNames.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AuthPolicy.java79
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientPNames.java133
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientParamBean.java106
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/CookiePolicy.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParamConfig.java88
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParams.java116
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContext.java132
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContextConfigurer.java72
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/HttpClientContext.java249
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAcceptEncoding.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAddCookies.java204
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthCache.java147
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthenticationBase.java126
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestClientConnControl.java92
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestDefaultHeaders.java89
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestExpectContinue.java82
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestProxyAuthentication.java92
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestTargetAuthentication.java83
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseAuthCache.java151
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseContentEncoding.java110
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseProcessCookies.java156
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/CloneUtils.java86
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/DateUtils.java250
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/HttpClientUtils.java149
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Idn.java42
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/JdkIdn.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Punycode.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Rfc3492Idn.java141
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIBuilder.java490
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIUtils.java428
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URLEncodedUtils.java628
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/BasicFuture.java154
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/Cancellable.java39
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/FutureCallback.java44
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/ConnectionConfig.java192
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Lookup.java40
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/MessageConstraints.java113
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Registry.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/RegistryBuilder.java72
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/SocketConfig.java197
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicEofSensorWatcher.java105
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicManagedEntity.java208
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManager.java117
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManagerFactory.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionOperator.java107
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionRequest.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectTimeoutException.java94
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java66
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionReleaseTrigger.java70
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionRequest.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/DnsResolver.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorInputStream.java289
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorWatcher.java95
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpClientConnectionManager.java176
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpConnectionFactory.java41
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpHostConnectException.java82
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpInetSocketAddress.java65
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpRoutedConnection.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedClientConnection.java228
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedHttpClientConnection.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/MultihomePlainSocketFactory.java173
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/OperatedClientConnection.java155
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/SchemePortResolver.java43
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/UnsupportedSchemeException.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionPNames.java64
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionParamBean.java59
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerPNames.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParamBean.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParams.java147
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRoute.java46
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRouteBean.java112
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRoutePNames.java79
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParamBean.java70
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParams.java178
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java181
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java328
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java161
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java366
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/HostNameResolver.java52
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java68
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java53
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/PlainSocketFactory.java160
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/Scheme.java260
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactory.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor2.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeRegistry.java168
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java130
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java100
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactory.java127
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java97
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/ConnectionSocketFactory.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/LayeredConnectionSocketFactory.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/PlainConnectionSocketFactory.java83
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AbstractVerifier.java386
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/DistinguishedNameParser.java131
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyDetails.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyStrategy.java44
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLConnectionSocketFactory.java295
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContextBuilder.java259
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContexts.java90
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLInitializationException.java37
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLSocketFactory.java570
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TokenParser.java266
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java45
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustStrategy.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java85
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/InetAddressUtils.java123
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/ClientCookie.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/Cookie.java137
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieAttributeHandler.java73
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieIdentityComparator.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieOrigin.java94
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookiePathComparator.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieRestrictionViolationException.java61
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpec.java109
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecFactory.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecProvider.java46
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecRegistry.java167
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/MalformedCookieException.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SM.java43
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie.java109
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie2.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecPNames.java65
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecParamBean.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/AbstractHttpEntity.java191
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BasicHttpEntity.java125
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BufferedHttpEntity.java125
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ByteArrayEntity.java131
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentLengthStrategy.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentProducer.java44
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentType.java305
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/EntityTemplate.java76
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/FileEntity.java121
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/HttpEntityWrapper.java105
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/InputStreamEntity.java155
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/SerializableEntity.java126
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/StringEntity.java188
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/AbstractMultipartForm.java211
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/FormBodyPart.java116
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/Header.java144
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpBrowserCompatibleMultipart.java79
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpMultipartMode.java43
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpRFC6532Multipart.java72
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpStrictMultipart.java72
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MIME.java53
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MinimalField.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartEntityBuilder.java207
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartFormEntity.java100
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/AbstractContentBody.java96
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ByteArrayBody.java111
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentBody.java43
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentDescriptor.java89
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/FileBody.java144
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/InputStreamBody.java112
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/StringBody.java197
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpClientConnection.java323
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpServerConnection.java310
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/BHttpConnectionBase.java393
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/ConnSupport.java75
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnection.java182
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnectionFactory.java103
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnection.java174
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnectionFactory.java103
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java189
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpClientConnection.java70
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpRequestFactory.java109
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpResponseFactory.java109
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpServerConnection.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java224
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/HttpConnectionMetricsImpl.java148
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/NoConnectionReuseStrategy.java53
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpClientConnection.java283
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpServerConnection.java271
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/AuthSchemeBase.java169
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicScheme.java219
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicSchemeFactory.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestScheme.java489
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestSchemeFactory.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpAuthenticator.java245
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpEntityDigester.java75
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngine.java70
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineException.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineImpl.java1672
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMScheme.java164
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMSchemeFactory.java56
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/RFC2617Scheme.java151
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AIMDBackoffManager.java164
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java189
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractHttpClient.java990
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyAdaptor.java172
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyImpl.java245
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AutoRetryHttpClient.java190
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicAuthCache.java105
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCookieStore.java144
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCredentialsProvider.java109
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicResponseHandler.java73
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ClientParamsStack.java269
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/Clock.java43
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpClient.java244
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpResponseProxy.java87
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ContentEncodingHttpClient.java93
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DecompressingHttpClient.java214
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultBackoffStrategy.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpClient.java225
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java203
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java90
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectHandler.java180
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategy.java233
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRequestDirector.java1150
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultServiceUnavailableRetryStrategy.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java91
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultUserTokenHandler.java101
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java113
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionMetrics.java156
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionService.java142
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpAuthenticator.java61
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClientBuilder.java954
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClients.java85
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestFutureTask.java118
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestTaskCallable.java119
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/InternalHttpClient.java242
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/LaxRedirectStrategy.java65
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/MinimalHttpClient.java156
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NoopUserTokenHandler.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NullBackoffStrategy.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyAuthenticationStrategy.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyClient.java254
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RedirectLocations.java227
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RequestWrapper.java164
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RoutedRequest.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/StandardHttpRequestRetryHandler.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemClock.java40
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultCredentialsProvider.java145
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultHttpClient.java149
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TargetAuthenticationStrategy.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TunnelRefusedException.java58
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidationRequest.java178
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidator.java150
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCache.java376
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCacheStorage.java96
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicIdGenerator.java86
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheConfig.java764
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntity.java99
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntryUpdater.java173
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheInvalidator.java288
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheKeyGenerator.java178
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheMap.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheValidityPolicy.java320
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheableRequestPolicy.java96
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedHttpResponseGenerator.java166
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedResponseSuitabilityChecker.java346
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingExec.java870
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClientBuilder.java149
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClients.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CombinedEntity.java104
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ConditionalRequestBuilder.java140
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultFailureCache.java143
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultHttpCacheEntrySerializer.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ExponentialBackOffSchedulingStrategy.java174
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCache.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCacheValue.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResource.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResourceFactory.java111
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResource.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResourceFactory.java83
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HttpCache.java166
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/IOUtils.java109
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ImmediateSchedulingStrategy.java88
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ManagedHttpCacheStorage.java163
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/OptionsHttp11Response.java182
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Proxies.java56
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolCompliance.java376
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolError.java40
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResourceReference.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseCachingPolicy.java311
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProtocolCompliance.java251
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProxyHandler.java88
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SchedulingStrategy.java45
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SizeLimitedResponseReader.java150
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Variant.java55
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/WarningValue.java370
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/package.html42
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/package-info.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java369
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPoolEntry.java262
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java191
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicClientConnectionManager.java276
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicHttpClientConnectionManager.java370
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPool.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolEntry.java101
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolProxy.java245
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ConnectionShutdownException.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnection.java292
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java263
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParser.java168
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParserFactory.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java123
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultManagedHttpClientConnection.java135
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultProxyRoutePlanner.java66
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultResponseParser.java125
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultRoutePlanner.java107
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultSchemePortResolver.java61
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpClientConnectionOperator.java173
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpConnPool.java84
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpPoolEntry.java98
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/IdleConnectionHandler.java181
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/InMemoryDnsResolver.java94
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingInputStream.java145
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingManagedHttpClientConnection.java132
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingOutputStream.java104
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java138
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java118
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedClientConnectionImpl.java461
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedHttpClientConnectionFactory.java121
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingClientConnectionManager.java328
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingHttpClientConnectionManager.java516
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java279
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SchemeRegistryFactory.java90
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SingleClientConnManager.java427
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultDnsResolver.java47
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultRoutePlanner.java132
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/Wire.java152
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java234
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java163
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java76
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java75
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java829
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java313
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java377
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThread.java198
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/package-info.java33
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java52
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieSpec.java104
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie.java361
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie2.java101
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicCommentHandler.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicDomainHandler.java116
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicExpiresHandler.java66
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java67
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicPathHandler.java87
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicSecureHandler.java60
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpec.java207
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java86
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpec.java219
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java92
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatVersionAttributeHandler.java66
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/CookieSpecBase.java121
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateParseException.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateUtils.java156
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpec.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java58
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java106
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java138
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java171
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixFilter.java132
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixListParser.java127
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java120
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109Spec.java240
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java86
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java66
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java66
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java185
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java160
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965Spec.java239
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java86
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java94
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/DisallowIdentityContentLengthStrategy.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntityDeserializer.java143
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntitySerializer.java121
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java126
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java116
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/BackoffStrategyExec.java104
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ClientExecChain.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ConnectionHolder.java153
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/HttpResponseProxy.java185
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MainClientExec.java568
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MinimalClientExec.java251
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ProtocolExec.java214
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RedirectExec.java185
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestAbortedException.java55
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestEntityProxy.java137
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ResponseEntityProxy.java152
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RetryExec.java126
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ServiceUnavailableRetryExec.java108
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/TunnelRefusedException.java55
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/package-info.java31
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageParser.java284
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageWriter.java119
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java401
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java307
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedInputStream.java301
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedOutputStream.java208
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthInputStream.java232
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthOutputStream.java136
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParser.java140
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParserFactory.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriter.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriterFactory.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParser.java141
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParserFactory.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriter.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriterFactory.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestParser.java102
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestWriter.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseParser.java103
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseWriter.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java63
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityInputStream.java99
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityOutputStream.java104
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionInputBufferImpl.java399
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionOutputBufferImpl.java283
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketInputBuffer.java108
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketOutputBuffer.java75
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnFactory.java177
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnPool.java89
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicPoolEntry.java64
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/BufferInfo.java58
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/EofSensor.java42
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParser.java56
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParserFactory.java42
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriter.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriterFactory.java41
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpTransportMetrics.java48
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionInputBuffer.java152
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionOutputBuffer.java120
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/AbstractHttpMessage.java164
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeader.java91
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElement.java162
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElementIterator.java151
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderIterator.java175
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueFormatter.java422
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueParser.java359
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java75
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpRequest.java114
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpResponse.java218
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineFormatter.java319
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineParser.java456
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicListHeaderIterator.java190
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicNameValuePair.java111
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicRequestLine.java83
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicStatusLine.java100
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicTokenIterator.java414
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BufferedHeader.java130
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderGroup.java311
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueFormatter.java122
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueParser.java134
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineFormatter.java131
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineParser.java137
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/ParserCursor.java100
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/package-info.java42
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/AbstractHttpParams.java124
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/BasicHttpParams.java190
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreConnectionPNames.java170
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreProtocolPNames.java152
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/DefaultedHttpParams.java163
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpAbstractParamBean.java48
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParamBean.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParams.java243
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamConfig.java78
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParams.java195
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamsNames.java57
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParamBean.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParams.java240
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/SyncBasicHttpParams.java89
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/AbstractConnPool.java533
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnFactory.java44
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPool.java68
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPoolControl.java56
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntry.java183
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryCallback.java41
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryFuture.java155
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolStats.java114
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/RouteSpecificPool.java184
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpContext.java95
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpProcessor.java246
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ChainBuilder.java126
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/DefaultedHttpContext.java84
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ExecutionContext.java80
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HTTP.java135
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpContext.java75
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpCoreContext.java152
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpDateGenerator.java77
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpExpectationVerifier.java81
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessor.java55
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessorBuilder.java151
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestExecutor.java311
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandler.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerMapper.java50
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java107
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerResolver.java51
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestInterceptorList.java103
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpResponseInterceptorList.java103
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpService.java447
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ImmutableHttpProcessor.java143
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestConnControl.java69
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestContent.java127
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestDate.java65
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestExpectContinue.java93
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestTargetHost.java95
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestUserAgent.java79
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseConnControl.java105
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseContent.java133
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseDate.java66
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseServer.java71
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/SyncBasicHttpContext.java74
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriHttpRequestHandlerMapper.java115
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriPatternMatcher.java165
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/package-info.java32
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Args.java111
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Asserts.java62
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ByteArrayBuffer.java347
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharArrayBuffer.java464
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharsetUtils.java58
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EncodingUtils.java152
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EntityUtils.java291
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ExceptionUtils.java82
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/LangUtils.java101
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/NetUtils.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/TextUtils.java54
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/VersionInfo.java324
-rw-r--r--mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/package-info.java31
708 files changed, 94851 insertions, 0 deletions
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionClosedException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionClosedException.java
new file mode 100644
index 000000000..bcd7308df
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionClosedException.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+/**
+ * Signals that the connection has been closed unexpectedly.
+ *
+ * @since 4.0
+ */
+public class ConnectionClosedException extends IOException {
+
+ private static final long serialVersionUID = 617550366255636674L;
+
+ /**
+ * Creates a new ConnectionClosedException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public ConnectionClosedException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionReuseStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionReuseStrategy.java
new file mode 100644
index 000000000..ec099b001
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ConnectionReuseStrategy.java
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Interface for deciding whether a connection can be re-used for
+ * subsequent requests and should be kept alive.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ */
+public interface ConnectionReuseStrategy {
+
+ /**
+ * Decides whether a connection can be kept open after a request.
+ * If this method returns <code>false</code>, the caller MUST
+ * close the connection to correctly comply with the HTTP protocol.
+ * If it returns <code>true</code>, the caller SHOULD attempt to
+ * keep the connection open for reuse with another request.
+ * <br/>
+ * One can use the HTTP context to retrieve additional objects that
+ * may be relevant for the keep-alive strategy: the actual HTTP
+ * connection, the original HTTP request, target host if known,
+ * number of times the connection has been reused already and so on.
+ * <br/>
+ * If the connection is already closed, <code>false</code> is returned.
+ * The stale connection check MUST NOT be triggered by a
+ * connection reuse strategy.
+ *
+ * @param response
+ * The last response received over that connection.
+ * @param context the context in which the connection is being
+ * used.
+ *
+ * @return <code>true</code> if the connection is allowed to be reused, or
+ * <code>false</code> if it MUST NOT be reused
+ */
+ boolean keepAlive(HttpResponse response, HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/Consts.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/Consts.java
new file mode 100644
index 000000000..81e2a7592
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/Consts.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.nio.charset.Charset;
+
+/**
+ * Commons constants.
+ *
+ * @since 4.2
+ */
+public final class Consts {
+
+ public static final int CR = 13; // <US-ASCII CR, carriage return (13)>
+ public static final int LF = 10; // <US-ASCII LF, linefeed (10)>
+ public static final int SP = 32; // <US-ASCII SP, space (32)>
+ public static final int HT = 9; // <US-ASCII HT, horizontal-tab (9)>
+
+ public static final Charset UTF_8 = Charset.forName("UTF-8");
+ public static final Charset ASCII = Charset.forName("US-ASCII");
+ public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+
+ private Consts() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ContentTooLongException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ContentTooLongException.java
new file mode 100644
index 000000000..64f83b3af
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ContentTooLongException.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+/**
+ * Signals that HTTP entity content is too long.
+ *
+ * @since 4.2
+ */
+public class ContentTooLongException extends IOException {
+
+ private static final long serialVersionUID = -924287689552495383L;
+
+ /**
+ * Creates a new ContentTooLongException with the specified detail message.
+ *
+ * @param message exception message
+ */
+ public ContentTooLongException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/FormattedHeader.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/FormattedHeader.java
new file mode 100644
index 000000000..cd3f4126d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/FormattedHeader.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * An HTTP header which is already formatted.
+ * For example when headers are received, the original formatting
+ * can be preserved. This allows for the header to be sent without
+ * another formatting step.
+ *
+ * @since 4.0
+ */
+public interface FormattedHeader extends Header {
+
+ /**
+ * Obtains the buffer with the formatted header.
+ * The returned buffer MUST NOT be modified.
+ *
+ * @return the formatted header, in a buffer that must not be modified
+ */
+ CharArrayBuffer getBuffer();
+
+ /**
+ * Obtains the start of the header value in the {@link #getBuffer buffer}.
+ * By accessing the value in the buffer, creation of a temporary string
+ * can be avoided.
+ *
+ * @return index of the first character of the header value
+ * in the buffer returned by {@link #getBuffer getBuffer}.
+ */
+ int getValuePos();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/Header.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/Header.java
new file mode 100644
index 000000000..50ce75a92
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/Header.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * Represents an HTTP header field.
+ *
+ * <p>The HTTP header fields follow the same generic format as
+ * that given in Section 3.1 of RFC 822. Each header field consists
+ * of a name followed by a colon (":") and the field value. Field names
+ * are case-insensitive. The field value MAY be preceded by any amount
+ * of LWS, though a single SP is preferred.
+ *
+ *<pre>
+ * message-header = field-name ":" [ field-value ]
+ * field-name = token
+ * field-value = *( field-content | LWS )
+ * field-content = &lt;the OCTETs making up the field-value
+ * and consisting of either *TEXT or combinations
+ * of token, separators, and quoted-string&gt;
+ *</pre>
+ *
+ * @since 4.0
+ */
+public interface Header {
+
+ /**
+ * Get the name of the Header.
+ *
+ * @return the name of the Header, never {@code null}
+ */
+ String getName();
+
+ /**
+ * Get the value of the Header.
+ *
+ * @return the value of the Header, may be {@code null}
+ */
+ String getValue();
+
+ /**
+ * Parses the value.
+ *
+ * @return an array of {@link HeaderElement} entries, may be empty, but is never {@code null}
+ * @throws ParseException
+ */
+ HeaderElement[] getElements() throws ParseException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElement.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElement.java
new file mode 100644
index 000000000..f6fcf8f04
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElement.java
@@ -0,0 +1,108 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * One element of an HTTP {@link Header header} value consisting of
+ * a name / value pair and a number of optional name / value parameters.
+ * <p>
+ * Some HTTP headers (such as the set-cookie header) have values that
+ * can be decomposed into multiple elements. Such headers must be in the
+ * following form:
+ * </p>
+ * <pre>
+ * header = [ element ] *( "," [ element ] )
+ * element = name [ "=" [ value ] ] *( ";" [ param ] )
+ * param = name [ "=" [ value ] ]
+ *
+ * name = token
+ * value = ( token | quoted-string )
+ *
+ * token = 1*&lt;any char except "=", ",", ";", &lt;"&gt; and
+ * white space&gt;
+ * quoted-string = &lt;"&gt; *( text | quoted-char ) &lt;"&gt;
+ * text = any char except &lt;"&gt;
+ * quoted-char = "\" char
+ * </pre>
+ * <p>
+ * Any amount of white space is allowed between any part of the
+ * header, element or param and is ignored. A missing value in any
+ * element or param will be stored as the empty {@link String};
+ * if the "=" is also missing <var>null</var> will be stored instead.
+ *
+ * @since 4.0
+ */
+public interface HeaderElement {
+
+ /**
+ * Returns header element name.
+ *
+ * @return header element name
+ */
+ String getName();
+
+ /**
+ * Returns header element value.
+ *
+ * @return header element value
+ */
+ String getValue();
+
+ /**
+ * Returns an array of name / value pairs.
+ *
+ * @return array of name / value pairs
+ */
+ NameValuePair[] getParameters();
+
+ /**
+ * Returns the first parameter with the given name.
+ *
+ * @param name parameter name
+ *
+ * @return name / value pair
+ */
+ NameValuePair getParameterByName(String name);
+
+ /**
+ * Returns the total count of parameters.
+ *
+ * @return parameter count
+ */
+ int getParameterCount();
+
+ /**
+ * Returns parameter with the given index.
+ *
+ * @param index index
+ * @return name / value pair
+ */
+ NameValuePair getParameter(int index);
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElementIterator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElementIterator.java
new file mode 100644
index 000000000..c0ef11346
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderElementIterator.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.util.Iterator;
+
+/**
+ * A type-safe iterator for {@link HeaderElement} objects.
+ *
+ * @since 4.0
+ */
+public interface HeaderElementIterator extends Iterator<Object> {
+
+ /**
+ * Indicates whether there is another header element in this
+ * iteration.
+ *
+ * @return <code>true</code> if there is another header element,
+ * <code>false</code> otherwise
+ */
+ boolean hasNext();
+
+ /**
+ * Obtains the next header element from this iteration.
+ * This method should only be called while {@link #hasNext hasNext}
+ * is true.
+ *
+ * @return the next header element in this iteration
+ */
+ HeaderElement nextElement();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderIterator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderIterator.java
new file mode 100644
index 000000000..a6879cea3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HeaderIterator.java
@@ -0,0 +1,56 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.util.Iterator;
+
+/**
+ * A type-safe iterator for {@link Header} objects.
+ *
+ * @since 4.0
+ */
+public interface HeaderIterator extends Iterator<Object> {
+
+ /**
+ * Indicates whether there is another header in this iteration.
+ *
+ * @return <code>true</code> if there is another header,
+ * <code>false</code> otherwise
+ */
+ boolean hasNext();
+
+ /**
+ * Obtains the next header from this iteration.
+ * This method should only be called while {@link #hasNext hasNext}
+ * is true.
+ *
+ * @return the next header in this iteration
+ */
+ Header nextHeader();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpClientConnection.java
new file mode 100644
index 000000000..f390700b6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpClientConnection.java
@@ -0,0 +1,102 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+/**
+ * A client-side HTTP connection, which can be used for sending
+ * requests and receiving responses.
+ *
+ * @since 4.0
+ */
+public interface HttpClientConnection extends HttpConnection {
+
+ /**
+ * Checks if response data is available from the connection. May wait for
+ * the specified time until some data becomes available. Note that some
+ * implementations may completely ignore the timeout parameter.
+ *
+ * @param timeout the maximum time in milliseconds to wait for data
+ * @return true if data is available; false if there was no data available
+ * even after waiting for <code>timeout</code> milliseconds.
+ * @throws IOException if an error happens on the connection
+ */
+ boolean isResponseAvailable(int timeout)
+ throws IOException;
+
+ /**
+ * Sends the request line and all headers over the connection.
+ * @param request the request whose headers to send.
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void sendRequestHeader(HttpRequest request)
+ throws HttpException, IOException;
+
+ /**
+ * Sends the request entity over the connection.
+ * @param request the request whose entity to send.
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void sendRequestEntity(HttpEntityEnclosingRequest request)
+ throws HttpException, IOException;
+
+ /**
+ * Receives the request line and headers of the next response available from
+ * this connection. The caller should examine the HttpResponse object to
+ * find out if it should try to receive a response entity as well.
+ *
+ * @return a new HttpResponse object with status line and headers
+ * initialized.
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ HttpResponse receiveResponseHeader()
+ throws HttpException, IOException;
+
+ /**
+ * Receives the next response entity available from this connection and
+ * attaches it to an existing HttpResponse object.
+ *
+ * @param response the response to attach the entity to
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void receiveResponseEntity(HttpResponse response)
+ throws HttpException, IOException;
+
+ /**
+ * Writes out all pending buffered data over the open connection.
+ *
+ * @throws IOException in case of an I/O error
+ */
+ void flush() throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnection.java
new file mode 100644
index 000000000..f4891358f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnection.java
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * A generic HTTP connection, useful on client and server side.
+ *
+ * @since 4.0
+ */
+public interface HttpConnection extends Closeable {
+
+ /**
+ * Closes this connection gracefully.
+ * This method will attempt to flush the internal output
+ * buffer prior to closing the underlying socket.
+ * This method MUST NOT be called from a different thread to force
+ * shutdown of the connection. Use {@link #shutdown shutdown} instead.
+ */
+ void close() throws IOException;
+
+ /**
+ * Checks if this connection is open.
+ * @return true if it is open, false if it is closed.
+ */
+ boolean isOpen();
+
+ /**
+ * Checks whether this connection has gone down.
+ * Network connections may get closed during some time of inactivity
+ * for several reasons. The next time a read is attempted on such a
+ * connection it will throw an IOException.
+ * This method tries to alleviate this inconvenience by trying to
+ * find out if a connection is still usable. Implementations may do
+ * that by attempting a read with a very small timeout. Thus this
+ * method may block for a small amount of time before returning a result.
+ * It is therefore an <i>expensive</i> operation.
+ *
+ * @return <code>true</code> if attempts to use this connection are
+ * likely to succeed, or <code>false</code> if they are likely
+ * to fail and this connection should be closed
+ */
+ boolean isStale();
+
+ /**
+ * Sets the socket timeout value.
+ *
+ * @param timeout timeout value in milliseconds
+ */
+ void setSocketTimeout(int timeout);
+
+ /**
+ * Returns the socket timeout value.
+ *
+ * @return positive value in milliseconds if a timeout is set,
+ * <code>0</code> if timeout is disabled or <code>-1</code> if
+ * timeout is undefined.
+ */
+ int getSocketTimeout();
+
+ /**
+ * Force-closes this connection.
+ * This is the only method of a connection which may be called
+ * from a different thread to terminate the connection.
+ * This method will not attempt to flush the transmitter's
+ * internal buffer prior to closing the underlying socket.
+ */
+ void shutdown() throws IOException;
+
+ /**
+ * Returns a collection of connection metrics.
+ *
+ * @return HttpConnectionMetrics
+ */
+ HttpConnectionMetrics getMetrics();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionFactory.java
new file mode 100644
index 000000000..867a1e9e0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionFactory.java
@@ -0,0 +1,42 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+import java.net.Socket;
+
+/**
+ * Factory for {@link HttpConnection} instances.
+ *
+ * @since 4.3
+ */
+public interface HttpConnectionFactory<T extends HttpConnection> {
+
+ T createConnection(Socket socket) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionMetrics.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionMetrics.java
new file mode 100644
index 000000000..4445eb55b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpConnectionMetrics.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * The point of access to the statistics of an {@link HttpConnection}.
+ *
+ * @since 4.0
+ */
+public interface HttpConnectionMetrics {
+
+ /**
+ * Returns the number of requests transferred over the connection,
+ * 0 if not available.
+ */
+ long getRequestCount();
+
+ /**
+ * Returns the number of responses transferred over the connection,
+ * 0 if not available.
+ */
+ long getResponseCount();
+
+ /**
+ * Returns the number of bytes transferred over the connection,
+ * 0 if not available.
+ */
+ long getSentBytesCount();
+
+ /**
+ * Returns the number of bytes transferred over the connection,
+ * 0 if not available.
+ */
+ long getReceivedBytesCount();
+
+ /**
+ * Return the value for the specified metric.
+ *
+ *@param metricName the name of the metric to query.
+ *
+ *@return the object representing the metric requested,
+ * <code>null</code> if the metric cannot not found.
+ */
+ Object getMetric(String metricName);
+
+ /**
+ * Resets the counts
+ *
+ */
+ void reset();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntity.java
new file mode 100644
index 000000000..5e223c1ec
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntity.java
@@ -0,0 +1,199 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * An entity that can be sent or received with an HTTP message.
+ * Entities can be found in some
+ * {@link HttpEntityEnclosingRequest requests} and in
+ * {@link HttpResponse responses}, where they are optional.
+ * <p>
+ * There are three distinct types of entities in HttpCore,
+ * depending on where their {@link #getContent content} originates:
+ * <ul>
+ * <li><b>streamed</b>: The content is received from a stream, or
+ * generated on the fly. In particular, this category includes
+ * entities being received from a {@link HttpConnection connection}.
+ * {@link #isStreaming Streamed} entities are generally not
+ * {@link #isRepeatable repeatable}.
+ * </li>
+ * <li><b>self-contained</b>: The content is in memory or obtained by
+ * means that are independent from a connection or other entity.
+ * Self-contained entities are generally {@link #isRepeatable repeatable}.
+ * </li>
+ * <li><b>wrapping</b>: The content is obtained from another entity.
+ * </li>
+ * </ul>
+ * This distinction is important for connection management with incoming
+ * entities. For entities that are created by an application and only sent
+ * using the HTTP components framework, the difference between streamed
+ * and self-contained is of little importance. In that case, it is suggested
+ * to consider non-repeatable entities as streamed, and those that are
+ * repeatable (without a huge effort) as self-contained.
+ *
+ * @since 4.0
+ */
+public interface HttpEntity {
+
+ /**
+ * Tells if the entity is capable of producing its data more than once.
+ * A repeatable entity's getContent() and writeTo(OutputStream) methods
+ * can be called more than once whereas a non-repeatable entity's can not.
+ * @return true if the entity is repeatable, false otherwise.
+ */
+ boolean isRepeatable();
+
+ /**
+ * Tells about chunked encoding for this entity.
+ * The primary purpose of this method is to indicate whether
+ * chunked encoding should be used when the entity is sent.
+ * For entities that are received, it can also indicate whether
+ * the entity was received with chunked encoding.
+ * <br/>
+ * The behavior of wrapping entities is implementation dependent,
+ * but should respect the primary purpose.
+ *
+ * @return <code>true</code> if chunked encoding is preferred for this
+ * entity, or <code>false</code> if it is not
+ */
+ boolean isChunked();
+
+ /**
+ * Tells the length of the content, if known.
+ *
+ * @return the number of bytes of the content, or
+ * a negative number if unknown. If the content length is known
+ * but exceeds {@link java.lang.Long#MAX_VALUE Long.MAX_VALUE},
+ * a negative number is returned.
+ */
+ long getContentLength();
+
+ /**
+ * Obtains the Content-Type header, if known.
+ * This is the header that should be used when sending the entity,
+ * or the one that was received with the entity. It can include a
+ * charset attribute.
+ *
+ * @return the Content-Type header for this entity, or
+ * <code>null</code> if the content type is unknown
+ */
+ Header getContentType();
+
+ /**
+ * Obtains the Content-Encoding header, if known.
+ * This is the header that should be used when sending the entity,
+ * or the one that was received with the entity.
+ * Wrapping entities that modify the content encoding should
+ * adjust this header accordingly.
+ *
+ * @return the Content-Encoding header for this entity, or
+ * <code>null</code> if the content encoding is unknown
+ */
+ Header getContentEncoding();
+
+ /**
+ * Returns a content stream of the entity.
+ * {@link #isRepeatable Repeatable} entities are expected
+ * to create a new instance of {@link InputStream} for each invocation
+ * of this method and therefore can be consumed multiple times.
+ * Entities that are not {@link #isRepeatable repeatable} are expected
+ * to return the same {@link InputStream} instance and therefore
+ * may not be consumed more than once.
+ * <p>
+ * IMPORTANT: Please note all entity implementations must ensure that
+ * all allocated resources are properly deallocated after
+ * the {@link InputStream#close()} method is invoked.
+ *
+ * @return content stream of the entity.
+ *
+ * @throws IOException if the stream could not be created
+ * @throws IllegalStateException
+ * if content stream cannot be created.
+ *
+ * @see #isRepeatable()
+ */
+ InputStream getContent() throws IOException, IllegalStateException;
+
+ /**
+ * Writes the entity content out to the output stream.
+ * <p>
+ * <p>
+ * IMPORTANT: Please note all entity implementations must ensure that
+ * all allocated resources are properly deallocated when this method
+ * returns.
+ *
+ * @param outstream the output stream to write entity content to
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ void writeTo(OutputStream outstream) throws IOException;
+
+ /**
+ * Tells whether this entity depends on an underlying stream.
+ * Streamed entities that read data directly from the socket should
+ * return <code>true</code>. Self-contained entities should return
+ * <code>false</code>. Wrapping entities should delegate this call
+ * to the wrapped entity.
+ *
+ * @return <code>true</code> if the entity content is streamed,
+ * <code>false</code> otherwise
+ */
+ boolean isStreaming(); // don't expect an exception here
+
+ /**
+ * This method is deprecated since version 4.1. Please use standard
+ * java convention to ensure resource deallocation by calling
+ * {@link InputStream#close()} on the input stream returned by
+ * {@link #getContent()}
+ * <p>
+ * This method is called to indicate that the content of this entity
+ * is no longer required. All entity implementations are expected to
+ * release all allocated resources as a result of this method
+ * invocation. Content streaming entities are also expected to
+ * dispose of the remaining content, if any. Wrapping entities should
+ * delegate this call to the wrapped entity.
+ * <p>
+ * This method is of particular importance for entities being
+ * received from a {@link HttpConnection connection}. The entity
+ * needs to be consumed completely in order to re-use the connection
+ * with keep-alive.
+ *
+ * @throws IOException if an I/O error occurs.
+ *
+ * @deprecated (4.1) Use {@link ch.boye.httpclientandroidlib.util.EntityUtils#consume(HttpEntity)}
+ *
+ * @see #getContent() and #writeTo(OutputStream)
+ */
+ @Deprecated
+ void consumeContent() throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntityEnclosingRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntityEnclosingRequest.java
new file mode 100644
index 000000000..f2cce4197
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpEntityEnclosingRequest.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib;
+
+/**
+ * A request with an entity.
+ *
+ * @since 4.0
+ */
+public interface HttpEntityEnclosingRequest extends HttpRequest {
+
+ /**
+ * Tells if this request should use the expect-continue handshake.
+ * The expect continue handshake gives the server a chance to decide
+ * whether to accept the entity enclosing request before the possibly
+ * lengthy entity is sent across the wire.
+ * @return true if the expect continue handshake should be used, false if
+ * not.
+ */
+ boolean expectContinue();
+
+ /**
+ * Associates the entity with this request.
+ *
+ * @param entity the entity to send.
+ */
+ void setEntity(HttpEntity entity);
+
+ /**
+ * Returns the entity associated with this request.
+ *
+ * @return entity
+ */
+ HttpEntity getEntity();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpException.java
new file mode 100644
index 000000000..05f6381d1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpException.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * Signals that an HTTP exception has occurred.
+ *
+ * @since 4.0
+ */
+public class HttpException extends Exception {
+
+ private static final long serialVersionUID = -5437299376222011036L;
+
+ /**
+ * Creates a new HttpException with a <tt>null</tt> detail message.
+ */
+ public HttpException() {
+ super();
+ }
+
+ /**
+ * Creates a new HttpException with the specified detail message.
+ *
+ * @param message the exception detail message
+ */
+ public HttpException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new HttpException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public HttpException(final String message, final Throwable cause) {
+ super(message);
+ initCause(cause);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHeaders.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHeaders.java
new file mode 100644
index 000000000..cadbced78
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHeaders.java
@@ -0,0 +1,206 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * Constants enumerating the HTTP headers. All headers defined in RFC1945 (HTTP/1.0), RFC2616 (HTTP/1.1), and RFC2518
+ * (WebDAV) are listed.
+ *
+ * @since 4.1
+ */
+public final class HttpHeaders {
+
+ private HttpHeaders() {
+ }
+
+ /** RFC 2616 (HTTP/1.1) Section 14.1 */
+ public static final String ACCEPT = "Accept";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.2 */
+ public static final String ACCEPT_CHARSET = "Accept-Charset";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.3 */
+ public static final String ACCEPT_ENCODING = "Accept-Encoding";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.4 */
+ public static final String ACCEPT_LANGUAGE = "Accept-Language";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.5 */
+ public static final String ACCEPT_RANGES = "Accept-Ranges";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.6 */
+ public static final String AGE = "Age";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.1, RFC 2616 (HTTP/1.1) Section 14.7 */
+ public static final String ALLOW = "Allow";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.2, RFC 2616 (HTTP/1.1) Section 14.8 */
+ public static final String AUTHORIZATION = "Authorization";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.9 */
+ public static final String CACHE_CONTROL = "Cache-Control";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.10 */
+ public static final String CONNECTION = "Connection";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.3, RFC 2616 (HTTP/1.1) Section 14.11 */
+ public static final String CONTENT_ENCODING = "Content-Encoding";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.12 */
+ public static final String CONTENT_LANGUAGE = "Content-Language";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.4, RFC 2616 (HTTP/1.1) Section 14.13 */
+ public static final String CONTENT_LENGTH = "Content-Length";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.14 */
+ public static final String CONTENT_LOCATION = "Content-Location";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.15 */
+ public static final String CONTENT_MD5 = "Content-MD5";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.16 */
+ public static final String CONTENT_RANGE = "Content-Range";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.5, RFC 2616 (HTTP/1.1) Section 14.17 */
+ public static final String CONTENT_TYPE = "Content-Type";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.6, RFC 2616 (HTTP/1.1) Section 14.18 */
+ public static final String DATE = "Date";
+
+ /** RFC 2518 (WevDAV) Section 9.1 */
+ public static final String DAV = "Dav";
+
+ /** RFC 2518 (WevDAV) Section 9.2 */
+ public static final String DEPTH = "Depth";
+
+ /** RFC 2518 (WevDAV) Section 9.3 */
+ public static final String DESTINATION = "Destination";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.19 */
+ public static final String ETAG = "ETag";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.20 */
+ public static final String EXPECT = "Expect";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.7, RFC 2616 (HTTP/1.1) Section 14.21 */
+ public static final String EXPIRES = "Expires";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.8, RFC 2616 (HTTP/1.1) Section 14.22 */
+ public static final String FROM = "From";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.23 */
+ public static final String HOST = "Host";
+
+ /** RFC 2518 (WevDAV) Section 9.4 */
+ public static final String IF = "If";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.24 */
+ public static final String IF_MATCH = "If-Match";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.9, RFC 2616 (HTTP/1.1) Section 14.25 */
+ public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.26 */
+ public static final String IF_NONE_MATCH = "If-None-Match";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.27 */
+ public static final String IF_RANGE = "If-Range";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.28 */
+ public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.10, RFC 2616 (HTTP/1.1) Section 14.29 */
+ public static final String LAST_MODIFIED = "Last-Modified";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.11, RFC 2616 (HTTP/1.1) Section 14.30 */
+ public static final String LOCATION = "Location";
+
+ /** RFC 2518 (WevDAV) Section 9.5 */
+ public static final String LOCK_TOKEN = "Lock-Token";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.31 */
+ public static final String MAX_FORWARDS = "Max-Forwards";
+
+ /** RFC 2518 (WevDAV) Section 9.6 */
+ public static final String OVERWRITE = "Overwrite";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.12, RFC 2616 (HTTP/1.1) Section 14.32 */
+ public static final String PRAGMA = "Pragma";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.33 */
+ public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.34 */
+ public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.35 */
+ public static final String RANGE = "Range";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.13, RFC 2616 (HTTP/1.1) Section 14.36 */
+ public static final String REFERER = "Referer";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.37 */
+ public static final String RETRY_AFTER = "Retry-After";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.14, RFC 2616 (HTTP/1.1) Section 14.38 */
+ public static final String SERVER = "Server";
+
+ /** RFC 2518 (WevDAV) Section 9.7 */
+ public static final String STATUS_URI = "Status-URI";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.39 */
+ public static final String TE = "TE";
+
+ /** RFC 2518 (WevDAV) Section 9.8 */
+ public static final String TIMEOUT = "Timeout";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.40 */
+ public static final String TRAILER = "Trailer";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.41 */
+ public static final String TRANSFER_ENCODING = "Transfer-Encoding";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.42 */
+ public static final String UPGRADE = "Upgrade";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.15, RFC 2616 (HTTP/1.1) Section 14.43 */
+ public static final String USER_AGENT = "User-Agent";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.44 */
+ public static final String VARY = "Vary";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.45 */
+ public static final String VIA = "Via";
+
+ /** RFC 2616 (HTTP/1.1) Section 14.46 */
+ public static final String WARNING = "Warning";
+
+ /** RFC 1945 (HTTP/1.0) Section 10.16, RFC 2616 (HTTP/1.1) Section 14.47 */
+ public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHost.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHost.java
new file mode 100644
index 000000000..d25bb13cf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpHost.java
@@ -0,0 +1,290 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Holds all of the variables needed to describe an HTTP connection to a host.
+ * This includes remote host name, port and scheme.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public final class HttpHost implements Cloneable, Serializable {
+
+ private static final long serialVersionUID = -7529410654042457626L;
+
+ /** The default scheme is "http". */
+ public static final String DEFAULT_SCHEME_NAME = "http";
+
+ /** The host to use. */
+ protected final String hostname;
+
+ /** The lowercase host, for {@link #equals} and {@link #hashCode}. */
+ protected final String lcHostname;
+
+
+ /** The port to use, defaults to -1 if not set. */
+ protected final int port;
+
+ /** The scheme (lowercased) */
+ protected final String schemeName;
+
+ protected final InetAddress address;
+
+ /**
+ * Creates a new {@link HttpHost HttpHost}, specifying all values.
+ * Constructor for HttpHost.
+ *
+ * @param hostname the hostname (IP or DNS name)
+ * @param port the port number.
+ * <code>-1</code> indicates the scheme default port.
+ * @param scheme the name of the scheme.
+ * <code>null</code> indicates the
+ * {@link #DEFAULT_SCHEME_NAME default scheme}
+ */
+ public HttpHost(final String hostname, final int port, final String scheme) {
+ super();
+ this.hostname = Args.notBlank(hostname, "Host name");
+ this.lcHostname = hostname.toLowerCase(Locale.ENGLISH);
+ if (scheme != null) {
+ this.schemeName = scheme.toLowerCase(Locale.ENGLISH);
+ } else {
+ this.schemeName = DEFAULT_SCHEME_NAME;
+ }
+ this.port = port;
+ this.address = null;
+ }
+
+ /**
+ * Creates a new {@link HttpHost HttpHost}, with default scheme.
+ *
+ * @param hostname the hostname (IP or DNS name)
+ * @param port the port number.
+ * <code>-1</code> indicates the scheme default port.
+ */
+ public HttpHost(final String hostname, final int port) {
+ this(hostname, port, null);
+ }
+
+ /**
+ * Creates a new {@link HttpHost HttpHost}, with default scheme and port.
+ *
+ * @param hostname the hostname (IP or DNS name)
+ */
+ public HttpHost(final String hostname) {
+ this(hostname, -1, null);
+ }
+
+ /**
+ * Creates a new {@link HttpHost HttpHost}, specifying all values.
+ * Constructor for HttpHost.
+ *
+ * @param address the inet address.
+ * @param port the port number.
+ * <code>-1</code> indicates the scheme default port.
+ * @param scheme the name of the scheme.
+ * <code>null</code> indicates the
+ * {@link #DEFAULT_SCHEME_NAME default scheme}
+ *
+ * @since 4.3
+ */
+ public HttpHost(final InetAddress address, final int port, final String scheme) {
+ super();
+ this.address = Args.notNull(address, "Inet address");
+ this.hostname = address.getHostAddress();
+ this.lcHostname = this.hostname.toLowerCase(Locale.ENGLISH);
+ if (scheme != null) {
+ this.schemeName = scheme.toLowerCase(Locale.ENGLISH);
+ } else {
+ this.schemeName = DEFAULT_SCHEME_NAME;
+ }
+ this.port = port;
+ }
+
+ /**
+ * Creates a new {@link HttpHost HttpHost}, with default scheme.
+ *
+ * @param address the inet address.
+ * @param port the port number.
+ * <code>-1</code> indicates the scheme default port.
+ *
+ * @since 4.3
+ */
+ public HttpHost(final InetAddress address, final int port) {
+ this(address, port, null);
+ }
+
+ /**
+ * Creates a new {@link HttpHost HttpHost}, with default scheme and port.
+ *
+ * @param address the inet address.
+ *
+ * @since 4.3
+ */
+ public HttpHost(final InetAddress address) {
+ this(address, -1, null);
+ }
+
+ /**
+ * Copy constructor for {@link HttpHost HttpHost}.
+ *
+ * @param httphost the HTTP host to copy details from
+ */
+ public HttpHost (final HttpHost httphost) {
+ super();
+ Args.notNull(httphost, "HTTP host");
+ this.hostname = httphost.hostname;
+ this.lcHostname = httphost.lcHostname;
+ this.schemeName = httphost.schemeName;
+ this.port = httphost.port;
+ this.address = httphost.address;
+ }
+
+ /**
+ * Returns the host name.
+ *
+ * @return the host name (IP or DNS name)
+ */
+ public String getHostName() {
+ return this.hostname;
+ }
+
+ /**
+ * Returns the port.
+ *
+ * @return the host port, or <code>-1</code> if not set
+ */
+ public int getPort() {
+ return this.port;
+ }
+
+ /**
+ * Returns the scheme name.
+ *
+ * @return the scheme name
+ */
+ public String getSchemeName() {
+ return this.schemeName;
+ }
+
+ /**
+ * Returns the inet address if explicitly set by a constructor,
+ * <code>null</code> otherwise.
+ * @return the inet address
+ *
+ * @since 4.3
+ */
+ public InetAddress getAddress() {
+ return this.address;
+ }
+
+ /**
+ * Return the host URI, as a string.
+ *
+ * @return the host URI
+ */
+ public String toURI() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(this.schemeName);
+ buffer.append("://");
+ buffer.append(this.hostname);
+ if (this.port != -1) {
+ buffer.append(':');
+ buffer.append(Integer.toString(this.port));
+ }
+ return buffer.toString();
+ }
+
+
+ /**
+ * Obtains the host string, without scheme prefix.
+ *
+ * @return the host string, for example <code>localhost:8080</code>
+ */
+ public String toHostString() {
+ if (this.port != -1) {
+ //the highest port number is 65535, which is length 6 with the addition of the colon
+ final StringBuilder buffer = new StringBuilder(this.hostname.length() + 6);
+ buffer.append(this.hostname);
+ buffer.append(":");
+ buffer.append(Integer.toString(this.port));
+ return buffer.toString();
+ } else {
+ return this.hostname;
+ }
+ }
+
+
+ @Override
+ public String toString() {
+ return toURI();
+ }
+
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HttpHost) {
+ final HttpHost that = (HttpHost) obj;
+ return this.lcHostname.equals(that.lcHostname)
+ && this.port == that.port
+ && this.schemeName.equals(that.schemeName);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.lcHostname);
+ hash = LangUtils.hashCode(hash, this.port);
+ hash = LangUtils.hashCode(hash, this.schemeName);
+ return hash;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpInetConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpInetConnection.java
new file mode 100644
index 000000000..9a22d3de8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpInetConnection.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.net.InetAddress;
+
+/**
+ * An HTTP connection over the Internet Protocol (IP).
+ *
+ * @since 4.0
+ */
+public interface HttpInetConnection extends HttpConnection {
+
+ InetAddress getLocalAddress();
+
+ int getLocalPort();
+
+ InetAddress getRemoteAddress();
+
+ int getRemotePort();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpMessage.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpMessage.java
new file mode 100644
index 000000000..9ea8a3e56
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpMessage.java
@@ -0,0 +1,210 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * HTTP messages consist of requests from client to server and responses
+ * from server to client.
+ * <pre>
+ * HTTP-message = Request | Response ; HTTP/1.1 messages
+ * </pre>
+ * <p>
+ * HTTP messages use the generic message format of RFC 822 for
+ * transferring entities (the payload of the message). Both types
+ * of message consist of a start-line, zero or more header fields
+ * (also known as "headers"), an empty line (i.e., a line with nothing
+ * preceding the CRLF) indicating the end of the header fields,
+ * and possibly a message-body.
+ * </p>
+ * <pre>
+ * generic-message = start-line
+ * *(message-header CRLF)
+ * CRLF
+ * [ message-body ]
+ * start-line = Request-Line | Status-Line
+ * </pre>
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+public interface HttpMessage {
+
+ /**
+ * Returns the protocol version this message is compatible with.
+ */
+ ProtocolVersion getProtocolVersion();
+
+ /**
+ * Checks if a certain header is present in this message. Header values are
+ * ignored.
+ *
+ * @param name the header name to check for.
+ * @return true if at least one header with this name is present.
+ */
+ boolean containsHeader(String name);
+
+ /**
+ * Returns all the headers with a specified name of this message. Header values
+ * are ignored. Headers are orderd in the sequence they will be sent over a
+ * connection.
+ *
+ * @param name the name of the headers to return.
+ * @return the headers whose name property equals <code>name</code>.
+ */
+ Header[] getHeaders(String name);
+
+ /**
+ * Returns the first header with a specified name of this message. Header
+ * values are ignored. If there is more than one matching header in the
+ * message the first element of {@link #getHeaders(String)} is returned.
+ * If there is no matching header in the message <code>null</code> is
+ * returned.
+ *
+ * @param name the name of the header to return.
+ * @return the first header whose name property equals <code>name</code>
+ * or <code>null</code> if no such header could be found.
+ */
+ Header getFirstHeader(String name);
+
+ /**
+ * Returns the last header with a specified name of this message. Header values
+ * are ignored. If there is more than one matching header in the message the
+ * last element of {@link #getHeaders(String)} is returned. If there is no
+ * matching header in the message <code>null</code> is returned.
+ *
+ * @param name the name of the header to return.
+ * @return the last header whose name property equals <code>name</code>.
+ * or <code>null</code> if no such header could be found.
+ */
+ Header getLastHeader(String name);
+
+ /**
+ * Returns all the headers of this message. Headers are orderd in the sequence
+ * they will be sent over a connection.
+ *
+ * @return all the headers of this message
+ */
+ Header[] getAllHeaders();
+
+ /**
+ * Adds a header to this message. The header will be appended to the end of
+ * the list.
+ *
+ * @param header the header to append.
+ */
+ void addHeader(Header header);
+
+ /**
+ * Adds a header to this message. The header will be appended to the end of
+ * the list.
+ *
+ * @param name the name of the header.
+ * @param value the value of the header.
+ */
+ void addHeader(String name, String value);
+
+ /**
+ * Overwrites the first header with the same name. The new header will be appended to
+ * the end of the list, if no header with the given name can be found.
+ *
+ * @param header the header to set.
+ */
+ void setHeader(Header header);
+
+ /**
+ * Overwrites the first header with the same name. The new header will be appended to
+ * the end of the list, if no header with the given name can be found.
+ *
+ * @param name the name of the header.
+ * @param value the value of the header.
+ */
+ void setHeader(String name, String value);
+
+ /**
+ * Overwrites all the headers in the message.
+ *
+ * @param headers the array of headers to set.
+ */
+ void setHeaders(Header[] headers);
+
+ /**
+ * Removes a header from this message.
+ *
+ * @param header the header to remove.
+ */
+ void removeHeader(Header header);
+
+ /**
+ * Removes all headers with a certain name from this message.
+ *
+ * @param name The name of the headers to remove.
+ */
+ void removeHeaders(String name);
+
+ /**
+ * Returns an iterator of all the headers.
+ *
+ * @return Iterator that returns Header objects in the sequence they are
+ * sent over a connection.
+ */
+ HeaderIterator headerIterator();
+
+ /**
+ * Returns an iterator of the headers with a given name.
+ *
+ * @param name the name of the headers over which to iterate, or
+ * <code>null</code> for all headers
+ *
+ * @return Iterator that returns Header objects with the argument name
+ * in the sequence they are sent over a connection.
+ */
+ HeaderIterator headerIterator(String name);
+
+ /**
+ * Returns the parameters effective for this message as set by
+ * {@link #setParams(HttpParams)}.
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+ @Deprecated
+ HttpParams getParams();
+
+ /**
+ * Provides parameters to be used for the processing of this message.
+ * @param params the parameters
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+ @Deprecated
+ void setParams(HttpParams params);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequest.java
new file mode 100644
index 000000000..20eff5f51
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequest.java
@@ -0,0 +1,53 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * A request message from a client to a server includes, within the
+ * first line of that message, the method to be applied to the resource,
+ * the identifier of the resource, and the protocol version in use.
+ * <pre>
+ * Request = Request-Line
+ * *(( general-header
+ * | request-header
+ * | entity-header ) CRLF)
+ * CRLF
+ * [ message-body ]
+ * </pre>
+ *
+ * @since 4.0
+ */
+public interface HttpRequest extends HttpMessage {
+
+ /**
+ * Returns the request line of this request.
+ * @return the request line.
+ */
+ RequestLine getRequestLine();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestFactory.java
new file mode 100644
index 000000000..ffc5dffda
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestFactory.java
@@ -0,0 +1,43 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * A factory for {@link HttpRequest HttpRequest} objects.
+ *
+ * @since 4.0
+ */
+public interface HttpRequestFactory {
+
+ HttpRequest newHttpRequest(RequestLine requestline)
+ throws MethodNotSupportedException;
+
+ HttpRequest newHttpRequest(String method, String uri)
+ throws MethodNotSupportedException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestInterceptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestInterceptor.java
new file mode 100644
index 000000000..b8efdaea0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpRequestInterceptor.java
@@ -0,0 +1,68 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * HTTP protocol interceptor is a routine that implements a specific aspect of
+ * the HTTP protocol. Usually protocol interceptors are expected to act upon
+ * one specific header or a group of related headers of the incoming message
+ * or populate the outgoing message with one specific header or a group of
+ * related headers.
+ * <p>
+ * Protocol Interceptors can also manipulate content entities enclosed with messages.
+ * Usually this is accomplished by using the 'Decorator' pattern where a wrapper
+ * entity class is used to decorate the original entity.
+ * <p>
+ * Protocol interceptors must be implemented as thread-safe. Similarly to
+ * servlets, protocol interceptors should not use instance variables unless
+ * access to those variables is synchronized.
+ *
+ * @since 4.0
+ */
+public interface HttpRequestInterceptor {
+
+ /**
+ * Processes a request.
+ * On the client side, this step is performed before the request is
+ * sent to the server. On the server side, this step is performed
+ * on incoming messages before the message body is evaluated.
+ *
+ * @param request the request to preprocess
+ * @param context the context for the request
+ *
+ * @throws HttpException in case of an HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void process(HttpRequest request, HttpContext context)
+ throws HttpException, IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponse.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponse.java
new file mode 100644
index 000000000..7d19952d5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponse.java
@@ -0,0 +1,155 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.util.Locale;
+
+/**
+ * After receiving and interpreting a request message, a server responds
+ * with an HTTP response message.
+ * <pre>
+ * Response = Status-Line
+ * *(( general-header
+ * | response-header
+ * | entity-header ) CRLF)
+ * CRLF
+ * [ message-body ]
+ * </pre>
+ *
+ * @since 4.0
+ */
+public interface HttpResponse extends HttpMessage {
+
+ /**
+ * Obtains the status line of this response.
+ * The status line can be set using one of the
+ * {@link #setStatusLine setStatusLine} methods,
+ * or it can be initialized in a constructor.
+ *
+ * @return the status line, or <code>null</code> if not yet set
+ */
+ StatusLine getStatusLine();
+
+ /**
+ * Sets the status line of this response.
+ *
+ * @param statusline the status line of this response
+ */
+ void setStatusLine(StatusLine statusline);
+
+ /**
+ * Sets the status line of this response.
+ * The reason phrase will be determined based on the current
+ * {@link #getLocale locale}.
+ *
+ * @param ver the HTTP version
+ * @param code the status code
+ */
+ void setStatusLine(ProtocolVersion ver, int code);
+
+ /**
+ * Sets the status line of this response with a reason phrase.
+ *
+ * @param ver the HTTP version
+ * @param code the status code
+ * @param reason the reason phrase, or <code>null</code> to omit
+ */
+ void setStatusLine(ProtocolVersion ver, int code, String reason);
+
+ /**
+ * Updates the status line of this response with a new status code.
+ *
+ * @param code the HTTP status code.
+ *
+ * @throws IllegalStateException
+ * if the status line has not be set
+ *
+ * @see HttpStatus
+ * @see #setStatusLine(StatusLine)
+ * @see #setStatusLine(ProtocolVersion,int)
+ */
+ void setStatusCode(int code)
+ throws IllegalStateException;
+
+ /**
+ * Updates the status line of this response with a new reason phrase.
+ *
+ * @param reason the new reason phrase as a single-line string, or
+ * <code>null</code> to unset the reason phrase
+ *
+ * @throws IllegalStateException
+ * if the status line has not be set
+ *
+ * @see #setStatusLine(StatusLine)
+ * @see #setStatusLine(ProtocolVersion,int)
+ */
+ void setReasonPhrase(String reason)
+ throws IllegalStateException;
+
+ /**
+ * Obtains the message entity of this response, if any.
+ * The entity is provided by calling {@link #setEntity setEntity}.
+ *
+ * @return the response entity, or
+ * <code>null</code> if there is none
+ */
+ HttpEntity getEntity();
+
+ /**
+ * Associates a response entity with this response.
+ * <p/>
+ * Please note that if an entity has already been set for this response and it depends on
+ * an input stream ({@link HttpEntity#isStreaming()} returns <code>true</code>),
+ * it must be fully consumed in order to ensure release of resources.
+ *
+ * @param entity the entity to associate with this response, or
+ * <code>null</code> to unset
+ *
+ * @see HttpEntity#isStreaming()
+ * @see ch.boye.httpclientandroidlib.util.EntityUtils#updateEntity(HttpResponse, HttpEntity)
+ */
+ void setEntity(HttpEntity entity);
+
+ /**
+ * Obtains the locale of this response.
+ * The locale is used to determine the reason phrase
+ * for the {@link #setStatusCode status code}.
+ * It can be changed using {@link #setLocale setLocale}.
+ *
+ * @return the locale of this response, never <code>null</code>
+ */
+ Locale getLocale();
+
+ /**
+ * Changes the locale of this response.
+ *
+ * @param loc the new locale
+ */
+ void setLocale(Locale loc);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseFactory.java
new file mode 100644
index 000000000..3897339c9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseFactory.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A factory for {@link HttpResponse HttpResponse} objects.
+ *
+ * @since 4.0
+ */
+public interface HttpResponseFactory {
+
+ /**
+ * Creates a new response from status line elements.
+ *
+ * @param ver the protocol version
+ * @param status the status code
+ * @param context the context from which to determine the locale
+ * for looking up a reason phrase to the status code, or
+ * <code>null</code> to use the default locale
+ *
+ * @return the new response with an initialized status line
+ */
+ HttpResponse newHttpResponse(ProtocolVersion ver, int status,
+ HttpContext context);
+
+ /**
+ * Creates a new response from a status line.
+ *
+ * @param statusline the status line
+ * @param context the context from which to determine the locale
+ * for looking up a reason phrase if the status code
+ * is updated, or
+ * <code>null</code> to use the default locale
+ *
+ * @return the new response with the argument status line
+ */
+ HttpResponse newHttpResponse(StatusLine statusline,
+ HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseInterceptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseInterceptor.java
new file mode 100644
index 000000000..6d4973c34
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpResponseInterceptor.java
@@ -0,0 +1,68 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * HTTP protocol interceptor is a routine that implements a specific aspect of
+ * the HTTP protocol. Usually protocol interceptors are expected to act upon
+ * one specific header or a group of related headers of the incoming message
+ * or populate the outgoing message with one specific header or a group of
+ * related headers. Protocol
+ * <p>
+ * Interceptors can also manipulate content entities enclosed with messages.
+ * Usually this is accomplished by using the 'Decorator' pattern where a wrapper
+ * entity class is used to decorate the original entity.
+ * <p>
+ * Protocol interceptors must be implemented as thread-safe. Similarly to
+ * servlets, protocol interceptors should not use instance variables unless
+ * access to those variables is synchronized.
+ *
+ * @since 4.0
+ */
+public interface HttpResponseInterceptor {
+
+ /**
+ * Processes a response.
+ * On the server side, this step is performed before the response is
+ * sent to the client. On the client side, this step is performed
+ * on incoming messages before the message body is evaluated.
+ *
+ * @param response the response to postprocess
+ * @param context the context for the request
+ *
+ * @throws HttpException in case of an HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void process(HttpResponse response, HttpContext context)
+ throws HttpException, IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpServerConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpServerConnection.java
new file mode 100644
index 000000000..9b0987dde
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpServerConnection.java
@@ -0,0 +1,88 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+/**
+ * A server-side HTTP connection, which can be used for receiving
+ * requests and sending responses.
+ *
+ * @since 4.0
+ */
+public interface HttpServerConnection extends HttpConnection {
+
+ /**
+ * Receives the request line and all headers available from this connection.
+ * The caller should examine the returned request and decide if to receive a
+ * request entity as well.
+ *
+ * @return a new HttpRequest object whose request line and headers are
+ * initialized.
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ HttpRequest receiveRequestHeader()
+ throws HttpException, IOException;
+
+ /**
+ * Receives the next request entity available from this connection and attaches it to
+ * an existing request.
+ * @param request the request to attach the entity to.
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void receiveRequestEntity(HttpEntityEnclosingRequest request)
+ throws HttpException, IOException;
+
+ /**
+ * Sends the response line and headers of a response over this connection.
+ * @param response the response whose headers to send.
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void sendResponseHeader(HttpResponse response)
+ throws HttpException, IOException;
+
+ /**
+ * Sends the response entity of a response over this connection.
+ * @param response the response whose entity to send.
+ * @throws HttpException in case of HTTP protocol violation
+ * @throws IOException in case of an I/O error
+ */
+ void sendResponseEntity(HttpResponse response)
+ throws HttpException, IOException;
+
+ /**
+ * Sends all pending buffered data over this connection.
+ * @throws IOException in case of an I/O error
+ */
+ void flush()
+ throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpStatus.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpStatus.java
new file mode 100644
index 000000000..1b61262a2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpStatus.java
@@ -0,0 +1,175 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * Constants enumerating the HTTP status codes.
+ * All status codes defined in RFC1945 (HTTP/1.0), RFC2616 (HTTP/1.1), and
+ * RFC2518 (WebDAV) are listed.
+ *
+ * @see StatusLine
+ *
+ * @since 4.0
+ */
+public interface HttpStatus {
+
+ // --- 1xx Informational ---
+
+ /** <tt>100 Continue</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_CONTINUE = 100;
+ /** <tt>101 Switching Protocols</tt> (HTTP/1.1 - RFC 2616)*/
+ public static final int SC_SWITCHING_PROTOCOLS = 101;
+ /** <tt>102 Processing</tt> (WebDAV - RFC 2518) */
+ public static final int SC_PROCESSING = 102;
+
+ // --- 2xx Success ---
+
+ /** <tt>200 OK</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_OK = 200;
+ /** <tt>201 Created</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_CREATED = 201;
+ /** <tt>202 Accepted</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_ACCEPTED = 202;
+ /** <tt>203 Non Authoritative Information</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
+ /** <tt>204 No Content</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_NO_CONTENT = 204;
+ /** <tt>205 Reset Content</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_RESET_CONTENT = 205;
+ /** <tt>206 Partial Content</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_PARTIAL_CONTENT = 206;
+ /**
+ * <tt>207 Multi-Status</tt> (WebDAV - RFC 2518) or <tt>207 Partial Update
+ * OK</tt> (HTTP/1.1 - draft-ietf-http-v11-spec-rev-01?)
+ */
+ public static final int SC_MULTI_STATUS = 207;
+
+ // --- 3xx Redirection ---
+
+ /** <tt>300 Mutliple Choices</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_MULTIPLE_CHOICES = 300;
+ /** <tt>301 Moved Permanently</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_MOVED_PERMANENTLY = 301;
+ /** <tt>302 Moved Temporarily</tt> (Sometimes <tt>Found</tt>) (HTTP/1.0 - RFC 1945) */
+ public static final int SC_MOVED_TEMPORARILY = 302;
+ /** <tt>303 See Other</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_SEE_OTHER = 303;
+ /** <tt>304 Not Modified</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_NOT_MODIFIED = 304;
+ /** <tt>305 Use Proxy</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_USE_PROXY = 305;
+ /** <tt>307 Temporary Redirect</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_TEMPORARY_REDIRECT = 307;
+
+ // --- 4xx Client Error ---
+
+ /** <tt>400 Bad Request</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_BAD_REQUEST = 400;
+ /** <tt>401 Unauthorized</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_UNAUTHORIZED = 401;
+ /** <tt>402 Payment Required</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_PAYMENT_REQUIRED = 402;
+ /** <tt>403 Forbidden</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_FORBIDDEN = 403;
+ /** <tt>404 Not Found</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_NOT_FOUND = 404;
+ /** <tt>405 Method Not Allowed</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_METHOD_NOT_ALLOWED = 405;
+ /** <tt>406 Not Acceptable</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_NOT_ACCEPTABLE = 406;
+ /** <tt>407 Proxy Authentication Required</tt> (HTTP/1.1 - RFC 2616)*/
+ public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
+ /** <tt>408 Request Timeout</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_REQUEST_TIMEOUT = 408;
+ /** <tt>409 Conflict</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_CONFLICT = 409;
+ /** <tt>410 Gone</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_GONE = 410;
+ /** <tt>411 Length Required</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_LENGTH_REQUIRED = 411;
+ /** <tt>412 Precondition Failed</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_PRECONDITION_FAILED = 412;
+ /** <tt>413 Request Entity Too Large</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_REQUEST_TOO_LONG = 413;
+ /** <tt>414 Request-URI Too Long</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_REQUEST_URI_TOO_LONG = 414;
+ /** <tt>415 Unsupported Media Type</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
+ /** <tt>416 Requested Range Not Satisfiable</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
+ /** <tt>417 Expectation Failed</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_EXPECTATION_FAILED = 417;
+
+ /**
+ * Static constant for a 418 error.
+ * <tt>418 Unprocessable Entity</tt> (WebDAV drafts?)
+ * or <tt>418 Reauthentication Required</tt> (HTTP/1.1 drafts?)
+ */
+ // not used
+ // public static final int SC_UNPROCESSABLE_ENTITY = 418;
+
+ /**
+ * Static constant for a 419 error.
+ * <tt>419 Insufficient Space on Resource</tt>
+ * (WebDAV - draft-ietf-webdav-protocol-05?)
+ * or <tt>419 Proxy Reauthentication Required</tt>
+ * (HTTP/1.1 drafts?)
+ */
+ public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
+ /**
+ * Static constant for a 420 error.
+ * <tt>420 Method Failure</tt>
+ * (WebDAV - draft-ietf-webdav-protocol-05?)
+ */
+ public static final int SC_METHOD_FAILURE = 420;
+ /** <tt>422 Unprocessable Entity</tt> (WebDAV - RFC 2518) */
+ public static final int SC_UNPROCESSABLE_ENTITY = 422;
+ /** <tt>423 Locked</tt> (WebDAV - RFC 2518) */
+ public static final int SC_LOCKED = 423;
+ /** <tt>424 Failed Dependency</tt> (WebDAV - RFC 2518) */
+ public static final int SC_FAILED_DEPENDENCY = 424;
+
+ // --- 5xx Server Error ---
+
+ /** <tt>500 Server Error</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_INTERNAL_SERVER_ERROR = 500;
+ /** <tt>501 Not Implemented</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_NOT_IMPLEMENTED = 501;
+ /** <tt>502 Bad Gateway</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_BAD_GATEWAY = 502;
+ /** <tt>503 Service Unavailable</tt> (HTTP/1.0 - RFC 1945) */
+ public static final int SC_SERVICE_UNAVAILABLE = 503;
+ /** <tt>504 Gateway Timeout</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_GATEWAY_TIMEOUT = 504;
+ /** <tt>505 HTTP Version Not Supported</tt> (HTTP/1.1 - RFC 2616) */
+ public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
+
+ /** <tt>507 Insufficient Storage</tt> (WebDAV - RFC 2518) */
+ public static final int SC_INSUFFICIENT_STORAGE = 507;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpVersion.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpVersion.java
new file mode 100644
index 000000000..3eae16172
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/HttpVersion.java
@@ -0,0 +1,110 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Represents an HTTP version. HTTP uses a "major.minor" numbering
+ * scheme to indicate versions of the protocol.
+ * <p>
+ * The version of an HTTP message is indicated by an HTTP-Version field
+ * in the first line of the message.
+ * </p>
+ * <pre>
+ * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+ * </pre>
+ *
+ * @since 4.0
+ */
+@Immutable
+public final class HttpVersion extends ProtocolVersion
+ implements Serializable {
+
+ private static final long serialVersionUID = -5856653513894415344L;
+
+ /** The protocol name. */
+ public static final String HTTP = "HTTP";
+
+ /** HTTP protocol version 0.9 */
+ public static final HttpVersion HTTP_0_9 = new HttpVersion(0, 9);
+
+ /** HTTP protocol version 1.0 */
+ public static final HttpVersion HTTP_1_0 = new HttpVersion(1, 0);
+
+ /** HTTP protocol version 1.1 */
+ public static final HttpVersion HTTP_1_1 = new HttpVersion(1, 1);
+
+
+ /**
+ * Create an HTTP protocol version designator.
+ *
+ * @param major the major version number of the HTTP protocol
+ * @param minor the minor version number of the HTTP protocol
+ *
+ * @throws IllegalArgumentException if either major or minor version number is negative
+ */
+ public HttpVersion(final int major, final int minor) {
+ super(HTTP, major, minor);
+ }
+
+
+ /**
+ * Obtains a specific HTTP version.
+ *
+ * @param major the major version
+ * @param minor the minor version
+ *
+ * @return an instance of {@link HttpVersion} with the argument version
+ */
+ @Override
+ public ProtocolVersion forVersion(final int major, final int minor) {
+
+ if ((major == this.major) && (minor == this.minor)) {
+ return this;
+ }
+
+ if (major == 1) {
+ if (minor == 0) {
+ return HTTP_1_0;
+ }
+ if (minor == 1) {
+ return HTTP_1_1;
+ }
+ }
+ if ((major == 0) && (minor == 9)) {
+ return HTTP_0_9;
+ }
+
+ // argument checking is done in the constructor
+ return new HttpVersion(major, minor);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MalformedChunkCodingException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MalformedChunkCodingException.java
new file mode 100644
index 000000000..7420ce08e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MalformedChunkCodingException.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+/**
+ * Signals a malformed chunked stream.
+ *
+ * @since 4.0
+ */
+public class MalformedChunkCodingException extends IOException {
+
+ private static final long serialVersionUID = 2158560246948994524L;
+
+ /**
+ * Creates a MalformedChunkCodingException without a detail message.
+ */
+ public MalformedChunkCodingException() {
+ super();
+ }
+
+ /**
+ * Creates a MalformedChunkCodingException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public MalformedChunkCodingException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MessageConstraintException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MessageConstraintException.java
new file mode 100644
index 000000000..cd6146194
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MessageConstraintException.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+/**
+ * Signals a message constraint violation.
+ *
+ * @since 4.3
+ */
+public class MessageConstraintException extends IOException {
+
+ private static final long serialVersionUID = 6077207720446368695L;
+
+ /**
+ * Creates a TruncatedChunkException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public MessageConstraintException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MethodNotSupportedException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MethodNotSupportedException.java
new file mode 100644
index 000000000..b418576df
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/MethodNotSupportedException.java
@@ -0,0 +1,59 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+
+/**
+ * Signals that an HTTP method is not supported.
+ *
+ * @since 4.0
+ */
+public class MethodNotSupportedException extends HttpException {
+
+ private static final long serialVersionUID = 3365359036840171201L;
+
+ /**
+ * Creates a new MethodNotSupportedException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public MethodNotSupportedException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new MethodNotSupportedException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public MethodNotSupportedException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/NameValuePair.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/NameValuePair.java
new file mode 100644
index 000000000..76ec354f9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/NameValuePair.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * A name / value pair parameter used as an element of HTTP messages.
+ * <pre>
+ * parameter = attribute "=" value
+ * attribute = token
+ * value = token | quoted-string
+ * </pre>
+ *
+ *
+ * @since 4.0
+ */
+public interface NameValuePair {
+
+ String getName();
+
+ String getValue();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/NoHttpResponseException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/NoHttpResponseException.java
new file mode 100644
index 000000000..1622da492
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/NoHttpResponseException.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.IOException;
+
+/**
+ * Signals that the target server failed to respond with a valid HTTP response.
+ *
+ * @since 4.0
+ */
+public class NoHttpResponseException extends IOException {
+
+ private static final long serialVersionUID = -7658940387386078766L;
+
+ /**
+ * Creates a new NoHttpResponseException with the specified detail message.
+ *
+ * @param message exception message
+ */
+ public NoHttpResponseException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ParseException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ParseException.java
new file mode 100644
index 000000000..1c3596485
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ParseException.java
@@ -0,0 +1,61 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * Signals a parse error.
+ * Parse errors when receiving a message will typically trigger
+ * {@link ProtocolException}. Parse errors that do not occur during
+ * protocol execution may be handled differently.
+ * This is an unchecked exception, since there are cases where
+ * the data to be parsed has been generated and is therefore
+ * known to be parseable.
+ *
+ * @since 4.0
+ */
+public class ParseException extends RuntimeException {
+
+ private static final long serialVersionUID = -7288819855864183578L;
+
+ /**
+ * Creates a {@link ParseException} without details.
+ */
+ public ParseException() {
+ super();
+ }
+
+ /**
+ * Creates a {@link ParseException} with a detail message.
+ *
+ * @param message the exception detail message, or <code>null</code>
+ */
+ public ParseException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolException.java
new file mode 100644
index 000000000..78fef4913
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolException.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * Signals that an HTTP protocol violation has occurred.
+ * For example a malformed status line or headers, a missing message body, etc.
+ *
+ *
+ * @since 4.0
+ */
+public class ProtocolException extends HttpException {
+
+ private static final long serialVersionUID = -2143571074341228994L;
+
+ /**
+ * Creates a new ProtocolException with a <tt>null</tt> detail message.
+ */
+ public ProtocolException() {
+ super();
+ }
+
+ /**
+ * Creates a new ProtocolException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public ProtocolException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new ProtocolException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public ProtocolException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolVersion.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolVersion.java
new file mode 100644
index 000000000..058d24f94
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ProtocolVersion.java
@@ -0,0 +1,264 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Represents a protocol version. The "major.minor" numbering
+ * scheme is used to indicate versions of the protocol.
+ * <p>
+ * This class defines a protocol version as a combination of
+ * protocol name, major version number, and minor version number.
+ * Note that {@link #equals} and {@link #hashCode} are defined as
+ * final here, they cannot be overridden in derived classes.
+ * </p>
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ProtocolVersion implements Serializable, Cloneable {
+
+ private static final long serialVersionUID = 8950662842175091068L;
+
+
+ /** Name of the protocol. */
+ protected final String protocol;
+
+ /** Major version number of the protocol */
+ protected final int major;
+
+ /** Minor version number of the protocol */
+ protected final int minor;
+
+
+ /**
+ * Create a protocol version designator.
+ *
+ * @param protocol the name of the protocol, for example "HTTP"
+ * @param major the major version number of the protocol
+ * @param minor the minor version number of the protocol
+ */
+ public ProtocolVersion(final String protocol, final int major, final int minor) {
+ this.protocol = Args.notNull(protocol, "Protocol name");
+ this.major = Args.notNegative(major, "Protocol minor version");
+ this.minor = Args.notNegative(minor, "Protocol minor version");
+ }
+
+ /**
+ * Returns the name of the protocol.
+ *
+ * @return the protocol name
+ */
+ public final String getProtocol() {
+ return protocol;
+ }
+
+ /**
+ * Returns the major version number of the protocol.
+ *
+ * @return the major version number.
+ */
+ public final int getMajor() {
+ return major;
+ }
+
+ /**
+ * Returns the minor version number of the HTTP protocol.
+ *
+ * @return the minor version number.
+ */
+ public final int getMinor() {
+ return minor;
+ }
+
+
+ /**
+ * Obtains a specific version of this protocol.
+ * This can be used by derived classes to instantiate themselves instead
+ * of the base class, and to define constants for commonly used versions.
+ * <br/>
+ * The default implementation in this class returns <code>this</code>
+ * if the version matches, and creates a new {@link ProtocolVersion}
+ * otherwise.
+ *
+ * @param major the major version
+ * @param minor the minor version
+ *
+ * @return a protocol version with the same protocol name
+ * and the argument version
+ */
+ public ProtocolVersion forVersion(final int major, final int minor) {
+
+ if ((major == this.major) && (minor == this.minor)) {
+ return this;
+ }
+
+ // argument checking is done in the constructor
+ return new ProtocolVersion(this.protocol, major, minor);
+ }
+
+
+ /**
+ * Obtains a hash code consistent with {@link #equals}.
+ *
+ * @return the hashcode of this protocol version
+ */
+ @Override
+ public final int hashCode() {
+ return this.protocol.hashCode() ^ (this.major * 100000) ^ this.minor;
+ }
+
+
+ /**
+ * Checks equality of this protocol version with an object.
+ * The object is equal if it is a protocl version with the same
+ * protocol name, major version number, and minor version number.
+ * The specific class of the object is <i>not</i> relevant,
+ * instances of derived classes with identical attributes are
+ * equal to instances of the base class and vice versa.
+ *
+ * @param obj the object to compare with
+ *
+ * @return <code>true</code> if the argument is the same protocol version,
+ * <code>false</code> otherwise
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ProtocolVersion)) {
+ return false;
+ }
+ final ProtocolVersion that = (ProtocolVersion) obj;
+
+ return ((this.protocol.equals(that.protocol)) &&
+ (this.major == that.major) &&
+ (this.minor == that.minor));
+ }
+
+
+ /**
+ * Checks whether this protocol can be compared to another one.
+ * Only protocol versions with the same protocol name can be
+ * {@link #compareToVersion compared}.
+ *
+ * @param that the protocol version to consider
+ *
+ * @return <code>true</code> if {@link #compareToVersion compareToVersion}
+ * can be called with the argument, <code>false</code> otherwise
+ */
+ public boolean isComparable(final ProtocolVersion that) {
+ return (that != null) && this.protocol.equals(that.protocol);
+ }
+
+
+ /**
+ * Compares this protocol version with another one.
+ * Only protocol versions with the same protocol name can be compared.
+ * This method does <i>not</i> define a total ordering, as it would be
+ * required for {@link java.lang.Comparable}.
+ *
+ * @param that the protocol version to compare with
+ *
+ * @return a negative integer, zero, or a positive integer
+ * as this version is less than, equal to, or greater than
+ * the argument version.
+ *
+ * @throws IllegalArgumentException
+ * if the argument has a different protocol name than this object,
+ * or if the argument is <code>null</code>
+ */
+ public int compareToVersion(final ProtocolVersion that) {
+ Args.notNull(that, "Protocol version");
+ Args.check(this.protocol.equals(that.protocol),
+ "Versions for different protocols cannot be compared: %s %s", this, that);
+ int delta = getMajor() - that.getMajor();
+ if (delta == 0) {
+ delta = getMinor() - that.getMinor();
+ }
+ return delta;
+ }
+
+
+ /**
+ * Tests if this protocol version is greater or equal to the given one.
+ *
+ * @param version the version against which to check this version
+ *
+ * @return <code>true</code> if this protocol version is
+ * {@link #isComparable comparable} to the argument
+ * and {@link #compareToVersion compares} as greater or equal,
+ * <code>false</code> otherwise
+ */
+ public final boolean greaterEquals(final ProtocolVersion version) {
+ return isComparable(version) && (compareToVersion(version) >= 0);
+ }
+
+
+ /**
+ * Tests if this protocol version is less or equal to the given one.
+ *
+ * @param version the version against which to check this version
+ *
+ * @return <code>true</code> if this protocol version is
+ * {@link #isComparable comparable} to the argument
+ * and {@link #compareToVersion compares} as less or equal,
+ * <code>false</code> otherwise
+ */
+ public final boolean lessEquals(final ProtocolVersion version) {
+ return isComparable(version) && (compareToVersion(version) <= 0);
+ }
+
+
+ /**
+ * Converts this protocol version to a string.
+ *
+ * @return a protocol version string, like "HTTP/1.1"
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(this.protocol);
+ buffer.append('/');
+ buffer.append(Integer.toString(this.major));
+ buffer.append('.');
+ buffer.append(Integer.toString(this.minor));
+ return buffer.toString();
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/README.txt b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/README.txt
new file mode 100644
index 000000000..cf4624ca4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/README.txt
@@ -0,0 +1 @@
+These files are managed in the android-sync repo. Do not modify directly, or your changes will be lost.
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ReasonPhraseCatalog.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ReasonPhraseCatalog.java
new file mode 100644
index 000000000..4cb5be0d0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/ReasonPhraseCatalog.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.util.Locale;
+
+/**
+ * Interface for obtaining reason phrases for HTTP status codes.
+ *
+ * @since 4.0
+ */
+public interface ReasonPhraseCatalog {
+
+ /**
+ * Obtains the reason phrase for a status code.
+ * The optional context allows for catalogs that detect
+ * the language for the reason phrase.
+ *
+ * @param status the status code, in the range 100-599
+ * @param loc the preferred locale for the reason phrase
+ *
+ * @return the reason phrase, or <code>null</code> if unknown
+ */
+ String getReason(int status, Locale loc);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/RequestLine.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/RequestLine.java
new file mode 100644
index 000000000..e44d737b7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/RequestLine.java
@@ -0,0 +1,49 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * The Request-Line begins with a method token, followed by the
+ * Request-URI and the protocol version, and ending with CRLF. The
+ * elements are separated by SP characters. No CR or LF is allowed
+ * except in the final CRLF sequence.
+ * <pre>
+ * Request-Line = Method SP Request-URI SP HTTP-Version CRLF
+ * </pre>
+ *
+ * @since 4.0
+ */
+public interface RequestLine {
+
+ String getMethod();
+
+ ProtocolVersion getProtocolVersion();
+
+ String getUri();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/StatusLine.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/StatusLine.java
new file mode 100644
index 000000000..741db7ab9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/StatusLine.java
@@ -0,0 +1,52 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * The first line of a Response message is the Status-Line, consisting
+ * of the protocol version followed by a numeric status code and its
+ * associated textual phrase, with each element separated by SP
+ * characters. No CR or LF is allowed except in the final CRLF sequence.
+ * <pre>
+ * Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+ * </pre>
+ *
+ * @see HttpStatus
+ * @version $Id: StatusLine.java 937295 2010-04-23 13:44:00Z olegk $
+ *
+ * @since 4.0
+ */
+public interface StatusLine {
+
+ ProtocolVersion getProtocolVersion();
+
+ int getStatusCode();
+
+ String getReasonPhrase();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/TokenIterator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/TokenIterator.java
new file mode 100644
index 000000000..4f7ea5d55
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/TokenIterator.java
@@ -0,0 +1,59 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+import java.util.Iterator;
+
+/**
+ * An iterator for {@link String} tokens.
+ * This interface is designed as a complement to
+ * {@link HeaderElementIterator}, in cases where the items
+ * are plain strings rather than full header elements.
+ *
+ * @since 4.0
+ */
+public interface TokenIterator extends Iterator<Object> {
+
+ /**
+ * Indicates whether there is another token in this iteration.
+ *
+ * @return <code>true</code> if there is another token,
+ * <code>false</code> otherwise
+ */
+ boolean hasNext();
+
+ /**
+ * Obtains the next token from this iteration.
+ * This method should only be called while {@link #hasNext hasNext}
+ * is true.
+ *
+ * @return the next token in this iteration
+ */
+ String nextToken();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/TruncatedChunkException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/TruncatedChunkException.java
new file mode 100644
index 000000000..1cb994923
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/TruncatedChunkException.java
@@ -0,0 +1,48 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+/**
+ * Signals a truncated chunk in a chunked stream.
+ *
+ * @since 4.1
+ */
+public class TruncatedChunkException extends MalformedChunkCodingException {
+
+ private static final long serialVersionUID = -23506263930279460L;
+
+ /**
+ * Creates a TruncatedChunkException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public TruncatedChunkException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/UnsupportedHttpVersionException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/UnsupportedHttpVersionException.java
new file mode 100644
index 000000000..15647f4c9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/UnsupportedHttpVersionException.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib;
+
+
+/**
+ * Signals an unsupported version of the HTTP protocol.
+ *
+ * @since 4.0
+ */
+public class UnsupportedHttpVersionException extends ProtocolException {
+
+ private static final long serialVersionUID = -1348448090193107031L;
+
+
+ /**
+ * Creates an exception without a detail message.
+ */
+ public UnsupportedHttpVersionException() {
+ super();
+ }
+
+ /**
+ * Creates an exception with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public UnsupportedHttpVersionException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/Base64.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/Base64.java
new file mode 100644
index 000000000..40f9801bd
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/Base64.java
@@ -0,0 +1,741 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.boye.httpclientandroidlib.androidextra;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Utilities for encoding and decoding the Base64 representation of
+ * binary data. See RFCs <a
+ * href="http://www.ietf.org/rfc/rfc2045.txt">2045</a> and <a
+ * href="http://www.ietf.org/rfc/rfc3548.txt">3548</a>.
+ */
+public class Base64 {
+ /**
+ * Default values for encoder/decoder flags.
+ */
+ public static final int DEFAULT = 0;
+
+ /**
+ * Encoder flag bit to omit the padding '=' characters at the end
+ * of the output (if any).
+ */
+ public static final int NO_PADDING = 1;
+
+ /**
+ * Encoder flag bit to omit all line terminators (i.e., the output
+ * will be on one long line).
+ */
+ public static final int NO_WRAP = 2;
+
+ /**
+ * Encoder flag bit to indicate lines should be terminated with a
+ * CRLF pair instead of just an LF. Has no effect if {@code
+ * NO_WRAP} is specified as well.
+ */
+ public static final int CRLF = 4;
+
+ /**
+ * Encoder/decoder flag bit to indicate using the "URL and
+ * filename safe" variant of Base64 (see RFC 3548 section 4) where
+ * {@code -} and {@code _} are used in place of {@code +} and
+ * {@code /}.
+ */
+ public static final int URL_SAFE = 8;
+
+ /**
+ * Flag to pass to {@link Base64OutputStream} to indicate that it
+ * should not close the output stream it is wrapping when it
+ * itself is closed.
+ */
+ public static final int NO_CLOSE = 16;
+
+ // --------------------------------------------------------
+ // shared code
+ // --------------------------------------------------------
+
+ /* package */ static abstract class Coder {
+ public byte[] output;
+ public int op;
+
+ /**
+ * Encode/decode another block of input data. this.output is
+ * provided by the caller, and must be big enough to hold all
+ * the coded data. On exit, this.opwill be set to the length
+ * of the coded data.
+ *
+ * @param finish true if this is the final call to process for
+ * this object. Will finalize the coder state and
+ * include any final bytes in the output.
+ *
+ * @return true if the input so far is good; false if some
+ * error has been detected in the input stream..
+ */
+ public abstract boolean process(byte[] input, int offset, int len, boolean finish);
+
+ /**
+ * @return the maximum number of bytes a call to process()
+ * could produce for the given number of input bytes. This may
+ * be an overestimate.
+ */
+ public abstract int maxOutputSize(int len);
+ }
+
+ // --------------------------------------------------------
+ // decoding
+ // --------------------------------------------------------
+
+ /**
+ * Decode the Base64-encoded data in input and return the data in
+ * a new byte array.
+ *
+ * <p>The padding '=' characters at the end are considered optional, but
+ * if any are present, there must be the correct number of them.
+ *
+ * @param str the input String to decode, which is converted to
+ * bytes using the default charset
+ * @param flags controls certain features of the decoded output.
+ * Pass {@code DEFAULT} to decode standard Base64.
+ *
+ * @throws IllegalArgumentException if the input contains
+ * incorrect padding
+ */
+ public static byte[] decode(String str, int flags) {
+ return decode(str.getBytes(), flags);
+ }
+
+ /**
+ * Decode the Base64-encoded data in input and return the data in
+ * a new byte array.
+ *
+ * <p>The padding '=' characters at the end are considered optional, but
+ * if any are present, there must be the correct number of them.
+ *
+ * @param input the input array to decode
+ * @param flags controls certain features of the decoded output.
+ * Pass {@code DEFAULT} to decode standard Base64.
+ *
+ * @throws IllegalArgumentException if the input contains
+ * incorrect padding
+ */
+ public static byte[] decode(byte[] input, int flags) {
+ return decode(input, 0, input.length, flags);
+ }
+
+ /**
+ * Decode the Base64-encoded data in input and return the data in
+ * a new byte array.
+ *
+ * <p>The padding '=' characters at the end are considered optional, but
+ * if any are present, there must be the correct number of them.
+ *
+ * @param input the data to decode
+ * @param offset the position within the input array at which to start
+ * @param len the number of bytes of input to decode
+ * @param flags controls certain features of the decoded output.
+ * Pass {@code DEFAULT} to decode standard Base64.
+ *
+ * @throws IllegalArgumentException if the input contains
+ * incorrect padding
+ */
+ public static byte[] decode(byte[] input, int offset, int len, int flags) {
+ // Allocate space for the most data the input could represent.
+ // (It could contain less if it contains whitespace, etc.)
+ Decoder decoder = new Decoder(flags, new byte[len*3/4]);
+
+ if (!decoder.process(input, offset, len, true)) {
+ throw new IllegalArgumentException("bad base-64");
+ }
+
+ // Maybe we got lucky and allocated exactly enough output space.
+ if (decoder.op == decoder.output.length) {
+ return decoder.output;
+ }
+
+ // Need to shorten the array, so allocate a new one of the
+ // right size and copy.
+ byte[] temp = new byte[decoder.op];
+ System.arraycopy(decoder.output, 0, temp, 0, decoder.op);
+ return temp;
+ }
+
+ /* package */ static class Decoder extends Coder {
+ /**
+ * Lookup table for turning bytes into their position in the
+ * Base64 alphabet.
+ */
+ private static final int DECODE[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+ /**
+ * Decode lookup table for the "web safe" variant (RFC 3548
+ * sec. 4) where - and _ replace + and /.
+ */
+ private static final int DECODE_WEBSAFE[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+ /** Non-data values in the DECODE arrays. */
+ private static final int SKIP = -1;
+ private static final int EQUALS = -2;
+
+ /**
+ * States 0-3 are reading through the next input tuple.
+ * State 4 is having read one '=' and expecting exactly
+ * one more.
+ * State 5 is expecting no more data or padding characters
+ * in the input.
+ * State 6 is the error state; an error has been detected
+ * in the input and no future input can "fix" it.
+ */
+ private int state; // state number (0 to 6)
+ private int value;
+
+ final private int[] alphabet;
+
+ public Decoder(int flags, byte[] output) {
+ this.output = output;
+
+ alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE;
+ state = 0;
+ value = 0;
+ }
+
+ /**
+ * @return an overestimate for the number of bytes {@code
+ * len} bytes could decode to.
+ */
+ public int maxOutputSize(int len) {
+ return len * 3/4 + 10;
+ }
+
+ /**
+ * Decode another block of input data.
+ *
+ * @return true if the state machine is still healthy. false if
+ * bad base-64 data has been detected in the input stream.
+ */
+ public boolean process(byte[] input, int offset, int len, boolean finish) {
+ if (this.state == 6) return false;
+
+ int p = offset;
+ len += offset;
+
+ // Using local variables makes the decoder about 12%
+ // faster than if we manipulate the member variables in
+ // the loop. (Even alphabet makes a measurable
+ // difference, which is somewhat surprising to me since
+ // the member variable is final.)
+ int state = this.state;
+ int value = this.value;
+ int op = 0;
+ final byte[] output = this.output;
+ final int[] alphabet = this.alphabet;
+
+ while (p < len) {
+ // Try the fast path: we're starting a new tuple and the
+ // next four bytes of the input stream are all data
+ // bytes. This corresponds to going through states
+ // 0-1-2-3-0. We expect to use this method for most of
+ // the data.
+ //
+ // If any of the next four bytes of input are non-data
+ // (whitespace, etc.), value will end up negative. (All
+ // the non-data values in decode are small negative
+ // numbers, so shifting any of them up and or'ing them
+ // together will result in a value with its top bit set.)
+ //
+ // You can remove this whole block and the output should
+ // be the same, just slower.
+ if (state == 0) {
+ while (p+4 <= len &&
+ (value = ((alphabet[input[p] & 0xff] << 18) |
+ (alphabet[input[p+1] & 0xff] << 12) |
+ (alphabet[input[p+2] & 0xff] << 6) |
+ (alphabet[input[p+3] & 0xff]))) >= 0) {
+ output[op+2] = (byte) value;
+ output[op+1] = (byte) (value >> 8);
+ output[op] = (byte) (value >> 16);
+ op += 3;
+ p += 4;
+ }
+ if (p >= len) break;
+ }
+
+ // The fast path isn't available -- either we've read a
+ // partial tuple, or the next four input bytes aren't all
+ // data, or whatever. Fall back to the slower state
+ // machine implementation.
+
+ int d = alphabet[input[p++] & 0xff];
+
+ switch (state) {
+ case 0:
+ if (d >= 0) {
+ value = d;
+ ++state;
+ } else if (d != SKIP) {
+ this.state = 6;
+ return false;
+ }
+ break;
+
+ case 1:
+ if (d >= 0) {
+ value = (value << 6) | d;
+ ++state;
+ } else if (d != SKIP) {
+ this.state = 6;
+ return false;
+ }
+ break;
+
+ case 2:
+ if (d >= 0) {
+ value = (value << 6) | d;
+ ++state;
+ } else if (d == EQUALS) {
+ // Emit the last (partial) output tuple;
+ // expect exactly one more padding character.
+ output[op++] = (byte) (value >> 4);
+ state = 4;
+ } else if (d != SKIP) {
+ this.state = 6;
+ return false;
+ }
+ break;
+
+ case 3:
+ if (d >= 0) {
+ // Emit the output triple and return to state 0.
+ value = (value << 6) | d;
+ output[op+2] = (byte) value;
+ output[op+1] = (byte) (value >> 8);
+ output[op] = (byte) (value >> 16);
+ op += 3;
+ state = 0;
+ } else if (d == EQUALS) {
+ // Emit the last (partial) output tuple;
+ // expect no further data or padding characters.
+ output[op+1] = (byte) (value >> 2);
+ output[op] = (byte) (value >> 10);
+ op += 2;
+ state = 5;
+ } else if (d != SKIP) {
+ this.state = 6;
+ return false;
+ }
+ break;
+
+ case 4:
+ if (d == EQUALS) {
+ ++state;
+ } else if (d != SKIP) {
+ this.state = 6;
+ return false;
+ }
+ break;
+
+ case 5:
+ if (d != SKIP) {
+ this.state = 6;
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (!finish) {
+ // We're out of input, but a future call could provide
+ // more.
+ this.state = state;
+ this.value = value;
+ this.op = op;
+ return true;
+ }
+
+ // Done reading input. Now figure out where we are left in
+ // the state machine and finish up.
+
+ switch (state) {
+ case 0:
+ // Output length is a multiple of three. Fine.
+ break;
+ case 1:
+ // Read one extra input byte, which isn't enough to
+ // make another output byte. Illegal.
+ this.state = 6;
+ return false;
+ case 2:
+ // Read two extra input bytes, enough to emit 1 more
+ // output byte. Fine.
+ output[op++] = (byte) (value >> 4);
+ break;
+ case 3:
+ // Read three extra input bytes, enough to emit 2 more
+ // output bytes. Fine.
+ output[op++] = (byte) (value >> 10);
+ output[op++] = (byte) (value >> 2);
+ break;
+ case 4:
+ // Read one padding '=' when we expected 2. Illegal.
+ this.state = 6;
+ return false;
+ case 5:
+ // Read all the padding '='s we expected and no more.
+ // Fine.
+ break;
+ }
+
+ this.state = state;
+ this.op = op;
+ return true;
+ }
+ }
+
+ // --------------------------------------------------------
+ // encoding
+ // --------------------------------------------------------
+
+ /**
+ * Base64-encode the given data and return a newly allocated
+ * String with the result.
+ *
+ * @param input the data to encode
+ * @param flags controls certain features of the encoded output.
+ * Passing {@code DEFAULT} results in output that
+ * adheres to RFC 2045.
+ */
+ public static String encodeToString(byte[] input, int flags) {
+ try {
+ return new String(encode(input, flags), "US-ASCII");
+ } catch (UnsupportedEncodingException e) {
+ // US-ASCII is guaranteed to be available.
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * Base64-encode the given data and return a newly allocated
+ * String with the result.
+ *
+ * @param input the data to encode
+ * @param offset the position within the input array at which to
+ * start
+ * @param len the number of bytes of input to encode
+ * @param flags controls certain features of the encoded output.
+ * Passing {@code DEFAULT} results in output that
+ * adheres to RFC 2045.
+ */
+ public static String encodeToString(byte[] input, int offset, int len, int flags) {
+ try {
+ return new String(encode(input, offset, len, flags), "US-ASCII");
+ } catch (UnsupportedEncodingException e) {
+ // US-ASCII is guaranteed to be available.
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * Base64-encode the given data and return a newly allocated
+ * byte[] with the result.
+ *
+ * @param input the data to encode
+ * @param flags controls certain features of the encoded output.
+ * Passing {@code DEFAULT} results in output that
+ * adheres to RFC 2045.
+ */
+ public static byte[] encode(byte[] input, int flags) {
+ return encode(input, 0, input.length, flags);
+ }
+
+ /**
+ * Base64-encode the given data and return a newly allocated
+ * byte[] with the result.
+ *
+ * @param input the data to encode
+ * @param offset the position within the input array at which to
+ * start
+ * @param len the number of bytes of input to encode
+ * @param flags controls certain features of the encoded output.
+ * Passing {@code DEFAULT} results in output that
+ * adheres to RFC 2045.
+ */
+ public static byte[] encode(byte[] input, int offset, int len, int flags) {
+ Encoder encoder = new Encoder(flags, null);
+
+ // Compute the exact length of the array we will produce.
+ int output_len = len / 3 * 4;
+
+ // Account for the tail of the data and the padding bytes, if any.
+ if (encoder.do_padding) {
+ if (len % 3 > 0) {
+ output_len += 4;
+ }
+ } else {
+ switch (len % 3) {
+ case 0: break;
+ case 1: output_len += 2; break;
+ case 2: output_len += 3; break;
+ }
+ }
+
+ // Account for the newlines, if any.
+ if (encoder.do_newline && len > 0) {
+ output_len += (((len-1) / (3 * Encoder.LINE_GROUPS)) + 1) *
+ (encoder.do_cr ? 2 : 1);
+ }
+
+ encoder.output = new byte[output_len];
+ encoder.process(input, offset, len, true);
+
+ assert encoder.op == output_len;
+
+ return encoder.output;
+ }
+
+ /* package */ static class Encoder extends Coder {
+ /**
+ * Emit a new line every this many output tuples. Corresponds to
+ * a 76-character line length (the maximum allowable according to
+ * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>).
+ */
+ public static final int LINE_GROUPS = 19;
+
+ /**
+ * Lookup table for turning Base64 alphabet positions (6 bits)
+ * into output bytes.
+ */
+ private static final byte ENCODE[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
+ };
+
+ /**
+ * Lookup table for turning Base64 alphabet positions (6 bits)
+ * into output bytes.
+ */
+ private static final byte ENCODE_WEBSAFE[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_',
+ };
+
+ final private byte[] tail;
+ /* package */ int tailLen;
+ private int count;
+
+ final public boolean do_padding;
+ final public boolean do_newline;
+ final public boolean do_cr;
+ final private byte[] alphabet;
+
+ public Encoder(int flags, byte[] output) {
+ this.output = output;
+
+ do_padding = (flags & NO_PADDING) == 0;
+ do_newline = (flags & NO_WRAP) == 0;
+ do_cr = (flags & CRLF) != 0;
+ alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE;
+
+ tail = new byte[2];
+ tailLen = 0;
+
+ count = do_newline ? LINE_GROUPS : -1;
+ }
+
+ /**
+ * @return an overestimate for the number of bytes {@code
+ * len} bytes could encode to.
+ */
+ public int maxOutputSize(int len) {
+ return len * 8/5 + 10;
+ }
+
+ public boolean process(byte[] input, int offset, int len, boolean finish) {
+ // Using local variables makes the encoder about 9% faster.
+ final byte[] alphabet = this.alphabet;
+ final byte[] output = this.output;
+ int op = 0;
+ int count = this.count;
+
+ int p = offset;
+ len += offset;
+ int v = -1;
+
+ // First we need to concatenate the tail of the previous call
+ // with any input bytes available now and see if we can empty
+ // the tail.
+
+ switch (tailLen) {
+ case 0:
+ // There was no tail.
+ break;
+
+ case 1:
+ if (p+2 <= len) {
+ // A 1-byte tail with at least 2 bytes of
+ // input available now.
+ v = ((tail[0] & 0xff) << 16) |
+ ((input[p++] & 0xff) << 8) |
+ (input[p++] & 0xff);
+ tailLen = 0;
+ };
+ break;
+
+ case 2:
+ if (p+1 <= len) {
+ // A 2-byte tail with at least 1 byte of input.
+ v = ((tail[0] & 0xff) << 16) |
+ ((tail[1] & 0xff) << 8) |
+ (input[p++] & 0xff);
+ tailLen = 0;
+ }
+ break;
+ }
+
+ if (v != -1) {
+ output[op++] = alphabet[(v >> 18) & 0x3f];
+ output[op++] = alphabet[(v >> 12) & 0x3f];
+ output[op++] = alphabet[(v >> 6) & 0x3f];
+ output[op++] = alphabet[v & 0x3f];
+ if (--count == 0) {
+ if (do_cr) output[op++] = '\r';
+ output[op++] = '\n';
+ count = LINE_GROUPS;
+ }
+ }
+
+ // At this point either there is no tail, or there are fewer
+ // than 3 bytes of input available.
+
+ // The main loop, turning 3 input bytes into 4 output bytes on
+ // each iteration.
+ while (p+3 <= len) {
+ v = ((input[p] & 0xff) << 16) |
+ ((input[p+1] & 0xff) << 8) |
+ (input[p+2] & 0xff);
+ output[op] = alphabet[(v >> 18) & 0x3f];
+ output[op+1] = alphabet[(v >> 12) & 0x3f];
+ output[op+2] = alphabet[(v >> 6) & 0x3f];
+ output[op+3] = alphabet[v & 0x3f];
+ p += 3;
+ op += 4;
+ if (--count == 0) {
+ if (do_cr) output[op++] = '\r';
+ output[op++] = '\n';
+ count = LINE_GROUPS;
+ }
+ }
+
+ if (finish) {
+ // Finish up the tail of the input. Note that we need to
+ // consume any bytes in tail before any bytes
+ // remaining in input; there should be at most two bytes
+ // total.
+
+ if (p-tailLen == len-1) {
+ int t = 0;
+ v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4;
+ tailLen -= t;
+ output[op++] = alphabet[(v >> 6) & 0x3f];
+ output[op++] = alphabet[v & 0x3f];
+ if (do_padding) {
+ output[op++] = '=';
+ output[op++] = '=';
+ }
+ if (do_newline) {
+ if (do_cr) output[op++] = '\r';
+ output[op++] = '\n';
+ }
+ } else if (p-tailLen == len-2) {
+ int t = 0;
+ v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) |
+ (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2);
+ tailLen -= t;
+ output[op++] = alphabet[(v >> 12) & 0x3f];
+ output[op++] = alphabet[(v >> 6) & 0x3f];
+ output[op++] = alphabet[v & 0x3f];
+ if (do_padding) {
+ output[op++] = '=';
+ }
+ if (do_newline) {
+ if (do_cr) output[op++] = '\r';
+ output[op++] = '\n';
+ }
+ } else if (do_newline && op > 0 && count != LINE_GROUPS) {
+ if (do_cr) output[op++] = '\r';
+ output[op++] = '\n';
+ }
+
+ assert tailLen == 0;
+ assert p == len;
+ } else {
+ // Save the leftovers in tail to be consumed on the next
+ // call to encodeInternal.
+
+ if (p == len-1) {
+ tail[tailLen++] = input[p];
+ } else if (p == len-2) {
+ tail[tailLen++] = input[p];
+ tail[tailLen++] = input[p+1];
+ }
+ }
+
+ this.op = op;
+ this.count = count;
+
+ return true;
+ }
+ }
+
+ private Base64() { } // don't instantiate
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/HttpClientAndroidLog.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/HttpClientAndroidLog.java
new file mode 100644
index 000000000..89758f315
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/androidextra/HttpClientAndroidLog.java
@@ -0,0 +1,113 @@
+package ch.boye.httpclientandroidlib.androidextra;
+
+import android.util.Log;
+
+public class HttpClientAndroidLog {
+
+ private String logTag;
+ private boolean debugEnabled;
+ private boolean errorEnabled;
+ private boolean traceEnabled;
+ private boolean warnEnabled;
+ private boolean infoEnabled;
+
+ public HttpClientAndroidLog(Object tag) {
+ logTag=tag.toString();
+ debugEnabled=false;
+ errorEnabled=false;
+ traceEnabled=false;
+ warnEnabled=false;
+ infoEnabled=false;
+ }
+
+ public void enableDebug(boolean enable) {
+ debugEnabled=enable;
+ }
+
+ public boolean isDebugEnabled() {
+ return debugEnabled;
+ }
+
+ public void debug(Object message) {
+ if(isDebugEnabled())
+ Log.d(logTag, message.toString());
+ }
+
+ public void debug(Object message, Throwable t) {
+ if(isDebugEnabled())
+ Log.d(logTag, message.toString(), t);
+ }
+
+ public void enableError(boolean enable) {
+ errorEnabled=enable;
+ }
+
+ public boolean isErrorEnabled() {
+ return errorEnabled;
+ }
+
+ public void error(Object message) {
+ if(isErrorEnabled())
+ Log.e(logTag, message.toString());
+ }
+
+ public void error(Object message, Throwable t) {
+ if(isErrorEnabled())
+ Log.e(logTag, message.toString(), t);
+ }
+
+ public void enableWarn(boolean enable) {
+ warnEnabled=enable;
+ }
+
+ public boolean isWarnEnabled() {
+ return warnEnabled;
+ }
+
+ public void warn(Object message) {
+ if(isWarnEnabled())
+ Log.w(logTag, message.toString());
+ }
+
+ public void warn(Object message, Throwable t) {
+ if(isWarnEnabled())
+ Log.w(logTag, message.toString(), t);
+ }
+
+ public void enableInfo(boolean enable) {
+ infoEnabled=enable;
+ }
+
+ public boolean isInfoEnabled() {
+ return infoEnabled;
+ }
+
+ public void info(Object message) {
+ if(isInfoEnabled())
+ Log.i(logTag, message.toString());
+ }
+
+ public void info(Object message, Throwable t) {
+ if(isInfoEnabled())
+ Log.i(logTag, message.toString(), t);
+ }
+
+ public void enableTrace(boolean enable) {
+ traceEnabled=enable;
+ }
+
+ public boolean isTraceEnabled() {
+ return traceEnabled;
+ }
+
+ public void trace(Object message) {
+ if(isTraceEnabled())
+ Log.i(logTag, message.toString());
+ }
+
+ public void trace(Object message, Throwable t) {
+ if(isTraceEnabled())
+ Log.i(logTag, message.toString(), t);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/GuardedBy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/GuardedBy.java
new file mode 100644
index 000000000..2a61da752
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/GuardedBy.java
@@ -0,0 +1,76 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The field or method to which this annotation is applied can only be accessed
+ * when holding a particular lock, which may be a built-in (synchronization) lock,
+ * or may be an explicit java.util.concurrent.Lock.
+ *
+ * The argument determines which lock guards the annotated field or method:
+ * <ul>
+ * <li>
+ * <code>this</code> : The intrinsic lock of the object in whose class the field is defined.
+ * </li>
+ * <li>
+ * <code>class-name.this</code> : For inner classes, it may be necessary to disambiguate 'this';
+ * the <em>class-name.this</em> designation allows you to specify which 'this' reference is intended
+ * </li>
+ * <li>
+ * <code>itself</code> : For reference fields only; the object to which the field refers.
+ * </li>
+ * <li>
+ * <code>field-name</code> : The lock object is referenced by the (instance or static) field
+ * specified by <em>field-name</em>.
+ * </li>
+ * <li>
+ * <code>class-name.field-name</code> : The lock object is reference by the static field specified
+ * by <em>class-name.field-name</em>.
+ * </li>
+ * <li>
+ * <code>method-name()</code> : The lock object is returned by calling the named nil-ary method.
+ * </li>
+ * <li>
+ * <code>class-name.class</code> : The Class object for the specified class should be used as the lock object.
+ * </li>
+ * <p>
+ * Based on code developed by Brian Goetz and Tim Peierls and concepts
+ * published in 'Java Concurrency in Practice' by Brian Goetz, Tim Peierls,
+ * Joshua Bloch, Joseph Bowbeer, David Holmes and Doug Lea.
+ */
+@Documented
+@Target({ElementType.FIELD, ElementType.METHOD})
+@Retention(RetentionPolicy.CLASS) // The original version used RUNTIME
+public @interface GuardedBy {
+ String value();
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/Immutable.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/Immutable.java
new file mode 100644
index 000000000..3aa8eb86e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/Immutable.java
@@ -0,0 +1,59 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The class to which this annotation is applied is immutable. This means that
+ * its state cannot be seen to change by callers, which implies that
+ * <ul>
+ * <li> all public fields are final, </li>
+ * <li> all public final reference fields refer to other immutable objects, and </li>
+ * <li> constructors and methods do not publish references to any internal state
+ * which is potentially mutable by the implementation. </li>
+ * </ul>
+ * Immutable objects may still have internal mutable state for purposes of performance
+ * optimization; some state variables may be lazily computed, so long as they are computed
+ * from immutable state and that callers cannot tell the difference.
+ * <p>
+ * Immutable objects are inherently thread-safe; they may be passed between threads or
+ * published without synchronization.
+ * <p>
+ * Based on code developed by Brian Goetz and Tim Peierls and concepts
+ * published in 'Java Concurrency in Practice' by Brian Goetz, Tim Peierls,
+ * Joshua Bloch, Joseph Bowbeer, David Holmes and Doug Lea.
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS) // The original version used RUNTIME
+public @interface Immutable {
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/NotThreadSafe.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/NotThreadSafe.java
new file mode 100644
index 000000000..0cab7dda2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/NotThreadSafe.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The class to which this annotation is applied is not thread-safe.
+ * This annotation primarily exists for clarifying the non-thread-safety of a class
+ * that might otherwise be assumed to be thread-safe, despite the fact that it is a bad
+ * idea to assume a class is thread-safe without good reason.
+ * @see ThreadSafe
+ * <p>
+ * Based on code developed by Brian Goetz and Tim Peierls and concepts
+ * published in 'Java Concurrency in Practice' by Brian Goetz, Tim Peierls,
+ * Joshua Bloch, Joseph Bowbeer, David Holmes and Doug Lea.
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS) // The original version used RUNTIME
+public @interface NotThreadSafe {
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/ThreadSafe.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/ThreadSafe.java
new file mode 100644
index 000000000..c8b1616d9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/ThreadSafe.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The class to which this annotation is applied is thread-safe. This means that
+ * no sequences of accesses (reads and writes to public fields, calls to public methods)
+ * may put the object into an invalid state, regardless of the interleaving of those actions
+ * by the runtime, and without requiring any additional synchronization or coordination on the
+ * part of the caller.
+ * @see NotThreadSafe
+ * <p>
+ * Based on code developed by Brian Goetz and Tim Peierls and concepts
+ * published in 'Java Concurrency in Practice' by Brian Goetz, Tim Peierls,
+ * Joshua Bloch, Joseph Bowbeer, David Holmes and Doug Lea.
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS) // The original version used RUNTIME
+public @interface ThreadSafe {
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/package-info.java
new file mode 100644
index 000000000..d74e8fef9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/annotation/package-info.java
@@ -0,0 +1,34 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Thread-safety annotations based on JCIP-ANNOTATIONS
+ * <br/>
+ * Copyright (c) 2005 Brian Goetz and Tim Peierls.
+ * See http://www.jcip.net
+ */
+package ch.boye.httpclientandroidlib.annotation;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AUTH.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AUTH.java
new file mode 100644
index 000000000..a0b50db73
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AUTH.java
@@ -0,0 +1,64 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Constants and static helpers related to the HTTP authentication.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public final class AUTH {
+
+ /**
+ * The www authenticate challange header.
+ */
+ public static final String WWW_AUTH = "WWW-Authenticate";
+
+ /**
+ * The www authenticate response header.
+ */
+ public static final String WWW_AUTH_RESP = "Authorization";
+
+ /**
+ * The proxy authenticate challange header.
+ */
+ public static final String PROXY_AUTH = "Proxy-Authenticate";
+
+ /**
+ * The proxy authenticate response header.
+ */
+ public static final String PROXY_AUTH_RESP = "Proxy-Authorization";
+
+ private AUTH() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthOption.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthOption.java
new file mode 100644
index 000000000..ae69df94d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthOption.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * @since 4.2
+ */
+@Immutable
+public final class AuthOption {
+
+ private final AuthScheme authScheme;
+ private final Credentials creds;
+
+ public AuthOption(final AuthScheme authScheme, final Credentials creds) {
+ super();
+ Args.notNull(authScheme, "Auth scheme");
+ Args.notNull(creds, "User credentials");
+ this.authScheme = authScheme;
+ this.creds = creds;
+ }
+
+ public AuthScheme getAuthScheme() {
+ return this.authScheme;
+ }
+
+ public Credentials getCredentials() {
+ return this.creds;
+ }
+
+ @Override
+ public String toString() {
+ return this.authScheme.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthProtocolState.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthProtocolState.java
new file mode 100644
index 000000000..081838915
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthProtocolState.java
@@ -0,0 +1,33 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+public enum AuthProtocolState {
+
+ UNCHALLENGED, CHALLENGED, HANDSHAKE, FAILURE, SUCCESS
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScheme.java
new file mode 100644
index 000000000..a028f182d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScheme.java
@@ -0,0 +1,130 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpRequest;
+
+/**
+ * This interface represents an abstract challenge-response oriented
+ * authentication scheme.
+ * <p>
+ * An authentication scheme should be able to support the following
+ * functions:
+ * <ul>
+ * <li>Parse and process the challenge sent by the target server
+ * in response to request for a protected resource
+ * <li>Provide its textual designation
+ * <li>Provide its parameters, if available
+ * <li>Provide the realm this authentication scheme is applicable to,
+ * if available
+ * <li>Generate authorization string for the given set of credentials
+ * and the HTTP request in response to the authorization challenge.
+ * </ul>
+ * <p>
+ * Authentication schemes may be stateful involving a series of
+ * challenge-response exchanges.
+ * <p>
+ * IMPORTANT: implementations of this interface MUST also implement {@link ContextAwareAuthScheme}
+ * interface in order to remain API compatible with newer versions of HttpClient.
+ *
+ * @since 4.0
+ */
+
+public interface AuthScheme {
+
+ /**
+ * Processes the given challenge token. Some authentication schemes
+ * may involve multiple challenge-response exchanges. Such schemes must be able
+ * to maintain the state information when dealing with sequential challenges
+ *
+ * @param header the challenge header
+ */
+ void processChallenge(final Header header) throws MalformedChallengeException;
+
+ /**
+ * Returns textual designation of the given authentication scheme.
+ *
+ * @return the name of the given authentication scheme
+ */
+ String getSchemeName();
+
+ /**
+ * Returns authentication parameter with the given name, if available.
+ *
+ * @param name The name of the parameter to be returned
+ *
+ * @return the parameter with the given name
+ */
+ String getParameter(final String name);
+
+ /**
+ * Returns authentication realm. If the concept of an authentication
+ * realm is not applicable to the given authentication scheme, returns
+ * <code>null</code>.
+ *
+ * @return the authentication realm
+ */
+ String getRealm();
+
+ /**
+ * Tests if the authentication scheme is provides authorization on a per
+ * connection basis instead of usual per request basis
+ *
+ * @return <tt>true</tt> if the scheme is connection based, <tt>false</tt>
+ * if the scheme is request based.
+ */
+ boolean isConnectionBased();
+
+ /**
+ * Authentication process may involve a series of challenge-response exchanges.
+ * This method tests if the authorization process has been completed, either
+ * successfully or unsuccessfully, that is, all the required authorization
+ * challenges have been processed in their entirety.
+ *
+ * @return <tt>true</tt> if the authentication process has been completed,
+ * <tt>false</tt> otherwise.
+ */
+ boolean isComplete();
+
+ /**
+ * Produces an authorization string for the given set of {@link Credentials}.
+ *
+ * @param credentials The set of credentials to be used for athentication
+ * @param request The request being authenticated
+ * @throws AuthenticationException if authorization string cannot
+ * be generated due to an authentication failure
+ *
+ * @return the authorization string
+ *
+ * @deprecated (4.1) Use {@link ContextAwareAuthScheme#authenticate(Credentials, HttpRequest, ch.boye.httpclientandroidlib.protocol.HttpContext)}
+ */
+ @Deprecated
+ Header authenticate(Credentials credentials, HttpRequest request)
+ throws AuthenticationException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeFactory.java
new file mode 100644
index 000000000..d88a3d06f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeFactory.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * Factory for {@link AuthScheme} implementations.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link AuthSchemeProvider}
+ */
+@Deprecated
+public interface AuthSchemeFactory {
+
+ /**
+ * Creates an instance of {@link AuthScheme} using given HTTP parameters.
+ *
+ * @param params HTTP parameters.
+ *
+ * @return auth scheme.
+ */
+ AuthScheme newInstance(HttpParams params);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeProvider.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeProvider.java
new file mode 100644
index 000000000..bfaf3f3cf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeProvider.java
@@ -0,0 +1,46 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Factory for {@link AuthScheme} implementations.
+ *
+ * @since 4.3
+ */
+public interface AuthSchemeProvider {
+
+ /**
+ * Creates an instance of {@link AuthScheme}.
+ *
+ * @return auth scheme.
+ */
+ AuthScheme create(HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeRegistry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeRegistry.java
new file mode 100644
index 000000000..4a6d15ca8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthSchemeRegistry.java
@@ -0,0 +1,155 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Authentication scheme registry that can be used to obtain the corresponding
+ * authentication scheme implementation for a given type of authorization challenge.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.config.Registry}
+ */
+@ThreadSafe
+@Deprecated
+public final class AuthSchemeRegistry implements Lookup<AuthSchemeProvider> {
+
+ private final ConcurrentHashMap<String,AuthSchemeFactory> registeredSchemes;
+
+ public AuthSchemeRegistry() {
+ super();
+ this.registeredSchemes = new ConcurrentHashMap<String,AuthSchemeFactory>();
+ }
+
+ /**
+ * Registers a {@link AuthSchemeFactory} with the given identifier. If a factory with the
+ * given name already exists it will be overridden. This name is the same one used to
+ * retrieve the {@link AuthScheme authentication scheme} from {@link #getAuthScheme}.
+ *
+ * <p>
+ * Please note that custom authentication preferences, if used, need to be updated accordingly
+ * for the new {@link AuthScheme authentication scheme} to take effect.
+ * </p>
+ *
+ * @param name the identifier for this scheme
+ * @param factory the {@link AuthSchemeFactory} class to register
+ *
+ * @see #getAuthScheme
+ */
+ public void register(
+ final String name,
+ final AuthSchemeFactory factory) {
+ Args.notNull(name, "Name");
+ Args.notNull(factory, "Authentication scheme factory");
+ registeredSchemes.put(name.toLowerCase(Locale.ENGLISH), factory);
+ }
+
+ /**
+ * Unregisters the class implementing an {@link AuthScheme authentication scheme} with
+ * the given name.
+ *
+ * @param name the identifier of the class to unregister
+ */
+ public void unregister(final String name) {
+ Args.notNull(name, "Name");
+ registeredSchemes.remove(name.toLowerCase(Locale.ENGLISH));
+ }
+
+ /**
+ * Gets the {@link AuthScheme authentication scheme} with the given name.
+ *
+ * @param name the {@link AuthScheme authentication scheme} identifier
+ * @param params the {@link HttpParams HTTP parameters} for the authentication
+ * scheme.
+ *
+ * @return {@link AuthScheme authentication scheme}
+ *
+ * @throws IllegalStateException if a scheme with the given name cannot be found
+ */
+ public AuthScheme getAuthScheme(final String name, final HttpParams params)
+ throws IllegalStateException {
+
+ Args.notNull(name, "Name");
+ final AuthSchemeFactory factory = registeredSchemes.get(name.toLowerCase(Locale.ENGLISH));
+ if (factory != null) {
+ return factory.newInstance(params);
+ } else {
+ throw new IllegalStateException("Unsupported authentication scheme: " + name);
+ }
+ }
+
+ /**
+ * Obtains a list containing the names of all registered {@link AuthScheme authentication
+ * schemes}
+ *
+ * @return list of registered scheme names
+ */
+ public List<String> getSchemeNames() {
+ return new ArrayList<String>(registeredSchemes.keySet());
+ }
+
+ /**
+ * Populates the internal collection of registered {@link AuthScheme authentication schemes}
+ * with the content of the map passed as a parameter.
+ *
+ * @param map authentication schemes
+ */
+ public void setItems(final Map<String, AuthSchemeFactory> map) {
+ if (map == null) {
+ return;
+ }
+ registeredSchemes.clear();
+ registeredSchemes.putAll(map);
+ }
+
+ public AuthSchemeProvider lookup(final String name) {
+ return new AuthSchemeProvider() {
+
+ public AuthScheme create(final HttpContext context) {
+ final HttpRequest request = (HttpRequest) context.getAttribute(
+ ExecutionContext.HTTP_REQUEST);
+ return getAuthScheme(name, request.getParams());
+ }
+
+ };
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScope.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScope.java
new file mode 100644
index 000000000..b6384729d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthScope.java
@@ -0,0 +1,302 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * The class represents an authentication scope consisting of a host name,
+ * a port number, a realm name and an authentication scheme name which
+ * {@link Credentials Credentials} apply to.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class AuthScope {
+
+ /**
+ * The <tt>null</tt> value represents any host. In the future versions of
+ * HttpClient the use of this parameter will be discontinued.
+ */
+ public static final String ANY_HOST = null;
+
+ /**
+ * The <tt>-1</tt> value represents any port.
+ */
+ public static final int ANY_PORT = -1;
+
+ /**
+ * The <tt>null</tt> value represents any realm.
+ */
+ public static final String ANY_REALM = null;
+
+ /**
+ * The <tt>null</tt> value represents any authentication scheme.
+ */
+ public static final String ANY_SCHEME = null;
+
+ /**
+ * Default scope matching any host, port, realm and authentication scheme.
+ * In the future versions of HttpClient the use of this parameter will be
+ * discontinued.
+ */
+ public static final AuthScope ANY = new AuthScope(ANY_HOST, ANY_PORT, ANY_REALM, ANY_SCHEME);
+
+ /** The authentication scheme the credentials apply to. */
+ private final String scheme;
+
+ /** The realm the credentials apply to. */
+ private final String realm;
+
+ /** The host the credentials apply to. */
+ private final String host;
+
+ /** The port the credentials apply to. */
+ private final int port;
+
+ /** Creates a new credentials scope for the given
+ * <tt>host</tt>, <tt>port</tt>, <tt>realm</tt>, and
+ * <tt>authentication scheme</tt>.
+ *
+ * @param host the host the credentials apply to. May be set
+ * to <tt>null</tt> if credentials are applicable to
+ * any host.
+ * @param port the port the credentials apply to. May be set
+ * to negative value if credentials are applicable to
+ * any port.
+ * @param realm the realm the credentials apply to. May be set
+ * to <tt>null</tt> if credentials are applicable to
+ * any realm.
+ * @param scheme the authentication scheme the credentials apply to.
+ * May be set to <tt>null</tt> if credentials are applicable to
+ * any authentication scheme.
+ */
+ public AuthScope(final String host, final int port,
+ final String realm, final String scheme)
+ {
+ this.host = (host == null) ? ANY_HOST: host.toLowerCase(Locale.ENGLISH);
+ this.port = (port < 0) ? ANY_PORT: port;
+ this.realm = (realm == null) ? ANY_REALM: realm;
+ this.scheme = (scheme == null) ? ANY_SCHEME: scheme.toUpperCase(Locale.ENGLISH);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public AuthScope(final HttpHost host, final String realm, final String schemeName) {
+ this(host.getHostName(), host.getPort(), realm, schemeName);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public AuthScope(final HttpHost host) {
+ this(host, ANY_REALM, ANY_SCHEME);
+ }
+
+ /** Creates a new credentials scope for the given
+ * <tt>host</tt>, <tt>port</tt>, <tt>realm</tt>, and any
+ * authentication scheme.
+ *
+ * @param host the host the credentials apply to. May be set
+ * to <tt>null</tt> if credentials are applicable to
+ * any host.
+ * @param port the port the credentials apply to. May be set
+ * to negative value if credentials are applicable to
+ * any port.
+ * @param realm the realm the credentials apply to. May be set
+ * to <tt>null</tt> if credentials are applicable to
+ * any realm.
+ */
+ public AuthScope(final String host, final int port, final String realm) {
+ this(host, port, realm, ANY_SCHEME);
+ }
+
+ /** Creates a new credentials scope for the given
+ * <tt>host</tt>, <tt>port</tt>, any realm name, and any
+ * authentication scheme.
+ *
+ * @param host the host the credentials apply to. May be set
+ * to <tt>null</tt> if credentials are applicable to
+ * any host.
+ * @param port the port the credentials apply to. May be set
+ * to negative value if credentials are applicable to
+ * any port.
+ */
+ public AuthScope(final String host, final int port) {
+ this(host, port, ANY_REALM, ANY_SCHEME);
+ }
+
+ /**
+ * Creates a copy of the given credentials scope.
+ */
+ public AuthScope(final AuthScope authscope) {
+ super();
+ Args.notNull(authscope, "Scope");
+ this.host = authscope.getHost();
+ this.port = authscope.getPort();
+ this.realm = authscope.getRealm();
+ this.scheme = authscope.getScheme();
+ }
+
+ /**
+ * @return the host
+ */
+ public String getHost() {
+ return this.host;
+ }
+
+ /**
+ * @return the port
+ */
+ public int getPort() {
+ return this.port;
+ }
+
+ /**
+ * @return the realm name
+ */
+ public String getRealm() {
+ return this.realm;
+ }
+
+ /**
+ * @return the scheme type
+ */
+ public String getScheme() {
+ return this.scheme;
+ }
+
+ /**
+ * Tests if the authentication scopes match.
+ *
+ * @return the match factor. Negative value signifies no match.
+ * Non-negative signifies a match. The greater the returned value
+ * the closer the match.
+ */
+ public int match(final AuthScope that) {
+ int factor = 0;
+ if (LangUtils.equals(this.scheme, that.scheme)) {
+ factor += 1;
+ } else {
+ if (this.scheme != ANY_SCHEME && that.scheme != ANY_SCHEME) {
+ return -1;
+ }
+ }
+ if (LangUtils.equals(this.realm, that.realm)) {
+ factor += 2;
+ } else {
+ if (this.realm != ANY_REALM && that.realm != ANY_REALM) {
+ return -1;
+ }
+ }
+ if (this.port == that.port) {
+ factor += 4;
+ } else {
+ if (this.port != ANY_PORT && that.port != ANY_PORT) {
+ return -1;
+ }
+ }
+ if (LangUtils.equals(this.host, that.host)) {
+ factor += 8;
+ } else {
+ if (this.host != ANY_HOST && that.host != ANY_HOST) {
+ return -1;
+ }
+ }
+ return factor;
+ }
+
+ /**
+ * @see java.lang.Object#equals(Object)
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof AuthScope)) {
+ return super.equals(o);
+ }
+ final AuthScope that = (AuthScope) o;
+ return
+ LangUtils.equals(this.host, that.host)
+ && this.port == that.port
+ && LangUtils.equals(this.realm, that.realm)
+ && LangUtils.equals(this.scheme, that.scheme);
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ if (this.scheme != null) {
+ buffer.append(this.scheme.toUpperCase(Locale.ENGLISH));
+ buffer.append(' ');
+ }
+ if (this.realm != null) {
+ buffer.append('\'');
+ buffer.append(this.realm);
+ buffer.append('\'');
+ } else {
+ buffer.append("<any realm>");
+ }
+ if (this.host != null) {
+ buffer.append('@');
+ buffer.append(this.host);
+ if (this.port >= 0) {
+ buffer.append(':');
+ buffer.append(this.port);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.host);
+ hash = LangUtils.hashCode(hash, this.port);
+ hash = LangUtils.hashCode(hash, this.realm);
+ hash = LangUtils.hashCode(hash, this.scheme);
+ return hash;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthState.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthState.java
new file mode 100644
index 000000000..236f934ac
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthState.java
@@ -0,0 +1,235 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.util.Queue;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * This class provides detailed information about the state of the authentication process.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class AuthState {
+
+ /** Actual state of authentication protocol */
+ private AuthProtocolState state;
+
+ /** Actual authentication scheme */
+ private AuthScheme authScheme;
+
+ /** Actual authentication scope */
+ private AuthScope authScope;
+
+ /** Credentials selected for authentication */
+ private Credentials credentials;
+
+ /** Available auth options */
+ private Queue<AuthOption> authOptions;
+
+ public AuthState() {
+ super();
+ this.state = AuthProtocolState.UNCHALLENGED;
+ }
+
+ /**
+ * Resets the auth state.
+ *
+ * @since 4.2
+ */
+ public void reset() {
+ this.state = AuthProtocolState.UNCHALLENGED;
+ this.authOptions = null;
+ this.authScheme = null;
+ this.authScope = null;
+ this.credentials = null;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public AuthProtocolState getState() {
+ return this.state;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void setState(final AuthProtocolState state) {
+ this.state = state != null ? state : AuthProtocolState.UNCHALLENGED;
+ }
+
+ /**
+ * Returns actual {@link AuthScheme}. May be null.
+ */
+ public AuthScheme getAuthScheme() {
+ return this.authScheme;
+ }
+
+ /**
+ * Returns actual {@link Credentials}. May be null.
+ */
+ public Credentials getCredentials() {
+ return this.credentials;
+ }
+
+ /**
+ * Updates the auth state with {@link AuthScheme} and {@link Credentials}.
+ *
+ * @param authScheme auth scheme. May not be null.
+ * @param credentials user crednetials. May not be null.
+ *
+ * @since 4.2
+ */
+ public void update(final AuthScheme authScheme, final Credentials credentials) {
+ Args.notNull(authScheme, "Auth scheme");
+ Args.notNull(credentials, "Credentials");
+ this.authScheme = authScheme;
+ this.credentials = credentials;
+ this.authOptions = null;
+ }
+
+ /**
+ * Returns available {@link AuthOption}s. May be null.
+ *
+ * @since 4.2
+ */
+ public Queue<AuthOption> getAuthOptions() {
+ return this.authOptions;
+ }
+
+ /**
+ * Returns <code>true</code> if {@link AuthOption}s are available, <code>false</code>
+ * otherwise.
+ *
+ * @since 4.2
+ */
+ public boolean hasAuthOptions() {
+ return this.authOptions != null && !this.authOptions.isEmpty();
+ }
+
+ /**
+ * Updates the auth state with a queue of {@link AuthOption}s.
+ *
+ * @param authOptions a queue of auth options. May not be null or empty.
+ *
+ * @since 4.2
+ */
+ public void update(final Queue<AuthOption> authOptions) {
+ Args.notEmpty(authOptions, "Queue of auth options");
+ this.authOptions = authOptions;
+ this.authScheme = null;
+ this.credentials = null;
+ }
+
+ /**
+ * Invalidates the authentication state by resetting its parameters.
+ *
+ * @deprecated (4.2) use {@link #reset()}
+ */
+ @Deprecated
+ public void invalidate() {
+ reset();
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ public boolean isValid() {
+ return this.authScheme != null;
+ }
+
+ /**
+ * Assigns the given {@link AuthScheme authentication scheme}.
+ *
+ * @param authScheme the {@link AuthScheme authentication scheme}
+ *
+ * @deprecated (4.2) use {@link #update(AuthScheme, Credentials)}
+ */
+ @Deprecated
+ public void setAuthScheme(final AuthScheme authScheme) {
+ if (authScheme == null) {
+ reset();
+ return;
+ }
+ this.authScheme = authScheme;
+ }
+
+ /**
+ * Sets user {@link Credentials} to be used for authentication
+ *
+ * @param credentials User credentials
+ *
+ * @deprecated (4.2) use {@link #update(AuthScheme, Credentials)}
+ */
+ @Deprecated
+ public void setCredentials(final Credentials credentials) {
+ this.credentials = credentials;
+ }
+
+ /**
+ * Returns actual {@link AuthScope} if available
+ *
+ * @return actual authentication scope if available, <code>null</code otherwise
+ *
+ * @deprecated (4.2) do not use.
+ */
+ @Deprecated
+ public AuthScope getAuthScope() {
+ return this.authScope;
+ }
+
+ /**
+ * Sets actual {@link AuthScope}.
+ *
+ * @param authScope Authentication scope
+ *
+ * @deprecated (4.2) do not use.
+ */
+ @Deprecated
+ public void setAuthScope(final AuthScope authScope) {
+ this.authScope = authScope;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("state:").append(this.state).append(";");
+ if (this.authScheme != null) {
+ buffer.append("auth scheme:").append(this.authScheme.getSchemeName()).append(";");
+ }
+ if (this.credentials != null) {
+ buffer.append("credentials present");
+ }
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthenticationException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthenticationException.java
new file mode 100644
index 000000000..e000e4d9b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/AuthenticationException.java
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals a failure in authentication process
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class AuthenticationException extends ProtocolException {
+
+ private static final long serialVersionUID = -6794031905674764776L;
+
+ /**
+ * Creates a new AuthenticationException with a <tt>null</tt> detail message.
+ */
+ public AuthenticationException() {
+ super();
+ }
+
+ /**
+ * Creates a new AuthenticationException with the specified message.
+ *
+ * @param message the exception detail message
+ */
+ public AuthenticationException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new AuthenticationException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public AuthenticationException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/BasicUserPrincipal.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/BasicUserPrincipal.java
new file mode 100644
index 000000000..e3bf323bb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/BasicUserPrincipal.java
@@ -0,0 +1,89 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Basic user principal used for HTTP authentication
+ *
+ * @since 4.0
+ */
+@Immutable
+public final class BasicUserPrincipal implements Principal, Serializable {
+
+ private static final long serialVersionUID = -2266305184969850467L;
+
+ private final String username;
+
+ public BasicUserPrincipal(final String username) {
+ super();
+ Args.notNull(username, "User name");
+ this.username = username;
+ }
+
+ public String getName() {
+ return this.username;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.username);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof BasicUserPrincipal) {
+ final BasicUserPrincipal that = (BasicUserPrincipal) o;
+ if (LangUtils.equals(this.username, that.username)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("[principal: ");
+ buffer.append(this.username);
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ChallengeState.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ChallengeState.java
new file mode 100644
index 000000000..8ff59b7bb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ChallengeState.java
@@ -0,0 +1,38 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+/**
+ * Challenge mode (TARGET or PROXY)
+ *
+ * @since 4.2
+ */
+public enum ChallengeState {
+
+ TARGET, PROXY
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ContextAwareAuthScheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ContextAwareAuthScheme.java
new file mode 100644
index 000000000..114679573
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/ContextAwareAuthScheme.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * This interface represents an extended authentication scheme
+ * that requires access to {@link HttpContext} in order to
+ * generate an authorization string.
+ *
+ * TODO: Fix AuthScheme interface in the next major version
+ *
+ * @since 4.1
+ */
+
+public interface ContextAwareAuthScheme extends AuthScheme {
+
+ /**
+ * Produces an authorization string for the given set of
+ * {@link Credentials}.
+ *
+ * @param credentials The set of credentials to be used for athentication
+ * @param request The request being authenticated
+ * @param context HTTP context
+ * @throws AuthenticationException if authorization string cannot
+ * be generated due to an authentication failure
+ *
+ * @return the authorization string
+ */
+ Header authenticate(
+ Credentials credentials,
+ HttpRequest request,
+ HttpContext context) throws AuthenticationException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/Credentials.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/Credentials.java
new file mode 100644
index 000000000..2c40ee10e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/Credentials.java
@@ -0,0 +1,44 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.security.Principal;
+
+/**
+ * This interface represents a set of credentials consisting of a security
+ * principal and a secret (password) that can be used to establish user
+ * identity
+ *
+ * @since 4.0
+ */
+public interface Credentials {
+
+ Principal getUserPrincipal();
+
+ String getPassword();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/InvalidCredentialsException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/InvalidCredentialsException.java
new file mode 100644
index 000000000..47d6e6d91
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/InvalidCredentialsException.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Authentication credentials required to respond to a authentication
+ * challenge are invalid
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class InvalidCredentialsException extends AuthenticationException {
+
+ private static final long serialVersionUID = -4834003835215460648L;
+
+ /**
+ * Creates a new InvalidCredentialsException with a <tt>null</tt> detail message.
+ */
+ public InvalidCredentialsException() {
+ super();
+ }
+
+ /**
+ * Creates a new InvalidCredentialsException with the specified message.
+ *
+ * @param message the exception detail message
+ */
+ public InvalidCredentialsException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new InvalidCredentialsException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public InvalidCredentialsException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/MalformedChallengeException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/MalformedChallengeException.java
new file mode 100644
index 000000000..309bbfb39
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/MalformedChallengeException.java
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals that authentication challenge is in some way invalid or
+ * illegal in the given context
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class MalformedChallengeException extends ProtocolException {
+
+ private static final long serialVersionUID = 814586927989932284L;
+
+ /**
+ * Creates a new MalformedChallengeException with a <tt>null</tt> detail message.
+ */
+ public MalformedChallengeException() {
+ super();
+ }
+
+ /**
+ * Creates a new MalformedChallengeException with the specified message.
+ *
+ * @param message the exception detail message
+ */
+ public MalformedChallengeException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new MalformedChallengeException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public MalformedChallengeException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTCredentials.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTCredentials.java
new file mode 100644
index 000000000..43693ffa2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTCredentials.java
@@ -0,0 +1,177 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * {@link Credentials} implementation for Microsoft Windows platforms that includes
+ * Windows specific attributes such as name of the domain the user belongs to.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class NTCredentials implements Credentials, Serializable {
+
+ private static final long serialVersionUID = -7385699315228907265L;
+
+ /** The user principal */
+ private final NTUserPrincipal principal;
+
+ /** Password */
+ private final String password;
+
+ /** The host the authentication request is originating from. */
+ private final String workstation;
+
+ /**
+ * The constructor with the fully qualified username and password combined
+ * string argument.
+ *
+ * @param usernamePassword the domain/username:password formed string
+ */
+ public NTCredentials(final String usernamePassword) {
+ super();
+ Args.notNull(usernamePassword, "Username:password string");
+ final String username;
+ final int atColon = usernamePassword.indexOf(':');
+ if (atColon >= 0) {
+ username = usernamePassword.substring(0, atColon);
+ this.password = usernamePassword.substring(atColon + 1);
+ } else {
+ username = usernamePassword;
+ this.password = null;
+ }
+ final int atSlash = username.indexOf('/');
+ if (atSlash >= 0) {
+ this.principal = new NTUserPrincipal(
+ username.substring(0, atSlash).toUpperCase(Locale.ENGLISH),
+ username.substring(atSlash + 1));
+ } else {
+ this.principal = new NTUserPrincipal(
+ null,
+ username.substring(atSlash + 1));
+ }
+ this.workstation = null;
+ }
+
+ /**
+ * Constructor.
+ * @param userName The user name. This should not include the domain to authenticate with.
+ * For example: "user" is correct whereas "DOMAIN\\user" is not.
+ * @param password The password.
+ * @param workstation The workstation the authentication request is originating from.
+ * Essentially, the computer name for this machine.
+ * @param domain The domain to authenticate within.
+ */
+ public NTCredentials(
+ final String userName,
+ final String password,
+ final String workstation,
+ final String domain) {
+ super();
+ Args.notNull(userName, "User name");
+ this.principal = new NTUserPrincipal(domain, userName);
+ this.password = password;
+ if (workstation != null) {
+ this.workstation = workstation.toUpperCase(Locale.ENGLISH);
+ } else {
+ this.workstation = null;
+ }
+ }
+
+ public Principal getUserPrincipal() {
+ return this.principal;
+ }
+
+ public String getUserName() {
+ return this.principal.getUsername();
+ }
+
+ public String getPassword() {
+ return this.password;
+ }
+
+ /**
+ * Retrieves the name to authenticate with.
+ *
+ * @return String the domain these credentials are intended to authenticate with.
+ */
+ public String getDomain() {
+ return this.principal.getDomain();
+ }
+
+ /**
+ * Retrieves the workstation name of the computer originating the request.
+ *
+ * @return String the workstation the user is logged into.
+ */
+ public String getWorkstation() {
+ return this.workstation;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.principal);
+ hash = LangUtils.hashCode(hash, this.workstation);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof NTCredentials) {
+ final NTCredentials that = (NTCredentials) o;
+ if (LangUtils.equals(this.principal, that.principal)
+ && LangUtils.equals(this.workstation, that.workstation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("[principal: ");
+ buffer.append(this.principal);
+ buffer.append("][workstation: ");
+ buffer.append(this.workstation);
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTUserPrincipal.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTUserPrincipal.java
new file mode 100644
index 000000000..13789ef4f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/NTUserPrincipal.java
@@ -0,0 +1,113 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Microsoft Windows specific user principal implementation.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class NTUserPrincipal implements Principal, Serializable {
+
+ private static final long serialVersionUID = -6870169797924406894L;
+
+ private final String username;
+ private final String domain;
+ private final String ntname;
+
+ public NTUserPrincipal(
+ final String domain,
+ final String username) {
+ super();
+ Args.notNull(username, "User name");
+ this.username = username;
+ if (domain != null) {
+ this.domain = domain.toUpperCase(Locale.ENGLISH);
+ } else {
+ this.domain = null;
+ }
+ if (this.domain != null && this.domain.length() > 0) {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(this.domain);
+ buffer.append('\\');
+ buffer.append(this.username);
+ this.ntname = buffer.toString();
+ } else {
+ this.ntname = this.username;
+ }
+ }
+
+ public String getName() {
+ return this.ntname;
+ }
+
+ public String getDomain() {
+ return this.domain;
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.username);
+ hash = LangUtils.hashCode(hash, this.domain);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof NTUserPrincipal) {
+ final NTUserPrincipal that = (NTUserPrincipal) o;
+ if (LangUtils.equals(this.username, that.username)
+ && LangUtils.equals(this.domain, that.domain)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return this.ntname;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/UsernamePasswordCredentials.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/UsernamePasswordCredentials.java
new file mode 100644
index 000000000..5cdeeb61e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/UsernamePasswordCredentials.java
@@ -0,0 +1,120 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.auth;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Simple {@link Credentials} implementation based on a user name / password
+ * pair.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class UsernamePasswordCredentials implements Credentials, Serializable {
+
+ private static final long serialVersionUID = 243343858802739403L;
+
+ private final BasicUserPrincipal principal;
+ private final String password;
+
+ /**
+ * The constructor with the username and password combined string argument.
+ *
+ * @param usernamePassword the username:password formed string
+ * @see #toString
+ */
+ public UsernamePasswordCredentials(final String usernamePassword) {
+ super();
+ Args.notNull(usernamePassword, "Username:password string");
+ final int atColon = usernamePassword.indexOf(':');
+ if (atColon >= 0) {
+ this.principal = new BasicUserPrincipal(usernamePassword.substring(0, atColon));
+ this.password = usernamePassword.substring(atColon + 1);
+ } else {
+ this.principal = new BasicUserPrincipal(usernamePassword);
+ this.password = null;
+ }
+ }
+
+
+ /**
+ * The constructor with the username and password arguments.
+ *
+ * @param userName the user name
+ * @param password the password
+ */
+ public UsernamePasswordCredentials(final String userName, final String password) {
+ super();
+ Args.notNull(userName, "Username");
+ this.principal = new BasicUserPrincipal(userName);
+ this.password = password;
+ }
+
+ public Principal getUserPrincipal() {
+ return this.principal;
+ }
+
+ public String getUserName() {
+ return this.principal.getName();
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.principal.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof UsernamePasswordCredentials) {
+ final UsernamePasswordCredentials that = (UsernamePasswordCredentials) o;
+ if (LangUtils.equals(this.principal, that.principal)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return this.principal.toString();
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/package-info.java
new file mode 100644
index 000000000..93992fcbf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client HTTP authentication APIs.
+ */
+package ch.boye.httpclientandroidlib.auth;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthPNames.java
new file mode 100644
index 000000000..ee64850ac
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthPNames.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.auth.params;
+
+/**
+ * Parameter names for HTTP authentication classes.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}
+ * and constructor parameters of
+ * {@link ch.boye.httpclientandroidlib.auth.AuthSchemeProvider}s.
+*/
+@Deprecated
+public interface AuthPNames {
+
+ /**
+ * Defines the charset to be used when encoding
+ * {@link ch.boye.httpclientandroidlib.auth.Credentials}.
+ * <p>
+ * This parameter expects a value of type {@link String}.
+ */
+ public static final String CREDENTIAL_CHARSET = "http.auth.credential-charset";
+
+ /**
+ * Defines the order of preference for supported
+ * {@link ch.boye.httpclientandroidlib.auth.AuthScheme}s when authenticating with
+ * the target host.
+ * <p>
+ * This parameter expects a value of type {@link java.util.Collection}. The
+ * collection is expected to contain {@link String} instances representing
+ * a name of an authentication scheme as returned by
+ * {@link ch.boye.httpclientandroidlib.auth.AuthScheme#getSchemeName()}.
+ */
+ public static final String TARGET_AUTH_PREF = "http.auth.target-scheme-pref";
+
+ /**
+ * Defines the order of preference for supported
+ * {@link ch.boye.httpclientandroidlib.auth.AuthScheme}s when authenticating with the
+ * proxy host.
+ * <p>
+ * This parameter expects a value of type {@link java.util.Collection}. The
+ * collection is expected to contain {@link String} instances representing
+ * a name of an authentication scheme as returned by
+ * {@link ch.boye.httpclientandroidlib.auth.AuthScheme#getSchemeName()}.
+ */
+ public static final String PROXY_AUTH_PREF = "http.auth.proxy-scheme-pref";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParamBean.java
new file mode 100644
index 000000000..e35d7ae28
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParamBean.java
@@ -0,0 +1,55 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.auth.params;
+
+import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate HTTP authentication parameters
+ * using Java Beans conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}
+ * and constructor parameters of
+ * {@link ch.boye.httpclientandroidlib.auth.AuthSchemeProvider}s.
+ */
+@Deprecated
+public class AuthParamBean extends HttpAbstractParamBean {
+
+ public AuthParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ public void setCredentialCharset (final String charset) {
+ AuthParams.setCredentialCharset(params, charset);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParams.java
new file mode 100644
index 000000000..cc7a3d32c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/AuthParams.java
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.auth.params;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * An adaptor for manipulating HTTP authentication parameters
+ * in {@link HttpParams}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}
+ * and constructor parameters of
+ * {@link ch.boye.httpclientandroidlib.auth.AuthSchemeProvider}s.
+ */
+@Immutable
+@Deprecated
+public final class AuthParams {
+
+ private AuthParams() {
+ super();
+ }
+
+ /**
+ * Obtains the charset for encoding
+ * {@link ch.boye.httpclientandroidlib.auth.Credentials}.If not configured,
+ * {@link HTTP#DEFAULT_PROTOCOL_CHARSET}is used instead.
+ *
+ * @return The charset
+ */
+ public static String getCredentialCharset(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ String charset = (String) params.getParameter
+ (AuthPNames.CREDENTIAL_CHARSET);
+ if (charset == null) {
+ charset = HTTP.DEF_PROTOCOL_CHARSET.name();
+ }
+ return charset;
+ }
+
+
+ /**
+ * Sets the charset to be used when encoding
+ * {@link ch.boye.httpclientandroidlib.auth.Credentials}.
+ *
+ * @param charset The charset
+ */
+ public static void setCredentialCharset(final HttpParams params, final String charset) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(AuthPNames.CREDENTIAL_CHARSET, charset);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/package-info.java
new file mode 100644
index 000000000..7b406b259
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/auth/params/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Deprecated.
+ * @deprecated (4.3).
+ */
+package ch.boye.httpclientandroidlib.auth.params;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthCache.java
new file mode 100644
index 000000000..3fd0a473d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthCache.java
@@ -0,0 +1,49 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+
+/**
+ * Abstract {@link AuthScheme} cache. Initialized {@link AuthScheme} objects
+ * from this cache can be used to preemptively authenticate against known
+ * hosts.
+ *
+ * @since 4.1
+ */
+public interface AuthCache {
+
+ void put(HttpHost host, AuthScheme authScheme);
+
+ AuthScheme get(HttpHost host);
+
+ void remove(HttpHost host);
+
+ void clear();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationHandler.java
new file mode 100644
index 000000000..24b30b54f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationHandler.java
@@ -0,0 +1,101 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+/**
+ * A handler for determining if an HTTP response represents an authentication
+ * challenge that was sent back to the client as a result of authentication
+ * failure.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link AuthenticationStrategy}
+ */
+@Deprecated
+public interface AuthenticationHandler {
+
+ /**
+ * Determines if the given HTTP response response represents
+ * an authentication challenge that was sent back as a result
+ * of authentication failure
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return <code>true</code> if user authentication is required,
+ * <code>false</code> otherwise.
+ */
+ boolean isAuthenticationRequested(
+ HttpResponse response,
+ HttpContext context);
+
+ /**
+ * Extracts from the given HTTP response a collection of authentication
+ * challenges, each of which represents an authentication scheme supported
+ * by the authentication host.
+ *
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return a collection of challenges keyed by names of corresponding
+ * authentication schemes.
+ * @throws MalformedChallengeException if one of the authentication
+ * challenges is not valid or malformed.
+ */
+ Map<String, Header> getChallenges(
+ HttpResponse response,
+ HttpContext context) throws MalformedChallengeException;
+
+ /**
+ * Selects one authentication challenge out of all available and
+ * creates and generates {@link AuthScheme} instance capable of
+ * processing that challenge.
+ * @param challenges collection of challenges.
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return authentication scheme to use for authentication.
+ * @throws AuthenticationException if an authentication scheme
+ * could not be selected.
+ */
+ AuthScheme selectScheme(
+ Map<String, Header> challenges,
+ HttpResponse response,
+ HttpContext context) throws AuthenticationException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationStrategy.java
new file mode 100644
index 000000000..2aa1fb536
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/AuthenticationStrategy.java
@@ -0,0 +1,130 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import java.util.Map;
+import java.util.Queue;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.auth.AuthOption;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+/**
+ * A handler for determining if an HTTP response represents an authentication challenge that was
+ * sent back to the client as a result of authentication failure.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared data must be
+ * synchronized as methods of this interface may be executed from multiple threads.
+ *
+ * @since 4.2
+ */
+public interface AuthenticationStrategy {
+
+ /**
+ * Determines if the given HTTP response response represents
+ * an authentication challenge that was sent back as a result
+ * of authentication failure.
+ *
+ * @param authhost authentication host.
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return <code>true</code> if user authentication is required,
+ * <code>false</code> otherwise.
+ */
+ boolean isAuthenticationRequested(
+ HttpHost authhost,
+ HttpResponse response,
+ HttpContext context);
+
+ /**
+ * Extracts from the given HTTP response a collection of authentication
+ * challenges, each of which represents an authentication scheme supported
+ * by the authentication host.
+ *
+ * @param authhost authentication host.
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return a collection of challenges keyed by names of corresponding
+ * authentication schemes.
+ * @throws MalformedChallengeException if one of the authentication
+ * challenges is not valid or malformed.
+ */
+ Map<String, Header> getChallenges(
+ HttpHost authhost,
+ HttpResponse response,
+ HttpContext context) throws MalformedChallengeException;
+
+ /**
+ * Selects one authentication challenge out of all available and
+ * creates and generates {@link AuthOption} instance capable of
+ * processing that challenge.
+ *
+ * @param challenges collection of challenges.
+ * @param authhost authentication host.
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return authentication auth schemes that can be used for authentication. Can be empty.
+ * @throws MalformedChallengeException if one of the authentication
+ * challenges is not valid or malformed.
+ */
+ Queue<AuthOption> select(
+ Map<String, Header> challenges,
+ HttpHost authhost,
+ HttpResponse response,
+ HttpContext context) throws MalformedChallengeException;
+
+ /**
+ * Callback invoked in case of successful authentication.
+ *
+ * @param authhost authentication host.
+ * @param authScheme authentication scheme used.
+ * @param context HTTP context.
+ */
+ void authSucceeded(
+ HttpHost authhost,
+ AuthScheme authScheme,
+ HttpContext context);
+
+ /**
+ * Callback invoked in case of unsuccessful authentication.
+ *
+ * @param authhost authentication host.
+ * @param authScheme authentication scheme used.
+ * @param context HTTP context.
+ */
+ void authFailed(
+ HttpHost authhost,
+ AuthScheme authScheme,
+ HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/BackoffManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/BackoffManager.java
new file mode 100644
index 000000000..afce4f277
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/BackoffManager.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+
+/**
+ * Represents a controller that dynamically adjusts the size
+ * of an available connection pool based on feedback from
+ * using the connections.
+ *
+ * @since 4.2
+ *
+ */
+public interface BackoffManager {
+
+ /**
+ * Called when we have decided that the result of
+ * using a connection should be interpreted as a
+ * backoff signal.
+ */
+ public void backOff(HttpRoute route);
+
+ /**
+ * Called when we have determined that the result of
+ * using a connection has succeeded and that we may
+ * probe for more connections.
+ */
+ public void probe(HttpRoute route);
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CircularRedirectException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CircularRedirectException.java
new file mode 100644
index 000000000..22d301885
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CircularRedirectException.java
@@ -0,0 +1,68 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals a circular redirect
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class CircularRedirectException extends RedirectException {
+
+ private static final long serialVersionUID = 6830063487001091803L;
+
+ /**
+ * Creates a new CircularRedirectException with a <tt>null</tt> detail message.
+ */
+ public CircularRedirectException() {
+ super();
+ }
+
+ /**
+ * Creates a new CircularRedirectException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public CircularRedirectException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new CircularRedirectException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public CircularRedirectException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ClientProtocolException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ClientProtocolException.java
new file mode 100644
index 000000000..3b807ae71
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ClientProtocolException.java
@@ -0,0 +1,61 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals an error in the HTTP protocol.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ClientProtocolException extends IOException {
+
+ private static final long serialVersionUID = -5596590843227115865L;
+
+ public ClientProtocolException() {
+ super();
+ }
+
+ public ClientProtocolException(final String s) {
+ super(s);
+ }
+
+ public ClientProtocolException(final Throwable cause) {
+ initCause(cause);
+ }
+
+ public ClientProtocolException(final String message, final Throwable cause) {
+ super(message);
+ initCause(cause);
+ }
+
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ConnectionBackoffStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ConnectionBackoffStrategy.java
new file mode 100644
index 000000000..1f30329cf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ConnectionBackoffStrategy.java
@@ -0,0 +1,64 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+/**
+ * When managing a dynamic number of connections for a given route, this
+ * strategy assesses whether a given request execution outcome should
+ * result in a backoff signal or not, based on either examining the
+ * <code>Throwable</code> that resulted or by examining the resulting
+ * response (e.g. for its status code).
+ *
+ * @since 4.2
+ *
+ */
+public interface ConnectionBackoffStrategy {
+
+ /**
+ * Determines whether seeing the given <code>Throwable</code> as
+ * a result of request execution should result in a backoff
+ * signal.
+ * @param t the <code>Throwable</code> that happened
+ * @return <code>true</code> if a backoff signal should be
+ * given
+ */
+ boolean shouldBackoff(Throwable t);
+
+ /**
+ * Determines whether receiving the given {@link HttpResponse} as
+ * a result of request execution should result in a backoff
+ * signal. Implementations MUST restrict themselves to examining
+ * the response header and MUST NOT consume any of the response
+ * body, if any.
+ * @param resp the <code>HttpResponse</code> that was received
+ * @return <code>true</code> if a backoff signal should be
+ * given
+ */
+ boolean shouldBackoff(HttpResponse resp);
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CookieStore.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CookieStore.java
new file mode 100644
index 000000000..683109ac4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CookieStore.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import java.util.Date;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+
+/**
+ * This interface represents an abstract store for {@link Cookie}
+ * objects.
+ *
+ * @since 4.0
+ */
+public interface CookieStore {
+
+ /**
+ * Adds an {@link Cookie}, replacing any existing equivalent cookies.
+ * If the given cookie has already expired it will not be added, but existing
+ * values will still be removed.
+ *
+ * @param cookie the {@link Cookie cookie} to be added
+ */
+ void addCookie(Cookie cookie);
+
+ /**
+ * Returns all cookies contained in this store.
+ *
+ * @return all cookies
+ */
+ List<Cookie> getCookies();
+
+ /**
+ * Removes all of {@link Cookie}s in this store that have expired by
+ * the specified {@link java.util.Date}.
+ *
+ * @return true if any cookies were purged.
+ */
+ boolean clearExpired(Date date);
+
+ /**
+ * Clears all cookies.
+ */
+ void clear();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CredentialsProvider.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CredentialsProvider.java
new file mode 100644
index 000000000..dc790399c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/CredentialsProvider.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+
+/**
+ * Abstract credentials provider that maintains a collection of user
+ * credentials.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ */
+public interface CredentialsProvider {
+
+ /**
+ * Sets the {@link Credentials credentials} for the given authentication
+ * scope. Any previous credentials for the given scope will be overwritten.
+ *
+ * @param authscope the {@link AuthScope authentication scope}
+ * @param credentials the authentication {@link Credentials credentials}
+ * for the given scope.
+ *
+ * @see #getCredentials(AuthScope)
+ */
+ void setCredentials(AuthScope authscope, Credentials credentials);
+
+ /**
+ * Get the {@link Credentials credentials} for the given authentication scope.
+ *
+ * @param authscope the {@link AuthScope authentication scope}
+ * @return the credentials
+ *
+ * @see #setCredentials(AuthScope, Credentials)
+ */
+ Credentials getCredentials(AuthScope authscope);
+
+ /**
+ * Clears all credentials.
+ */
+ void clear();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpClient.java
new file mode 100644
index 000000000..4cc87fcfe
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpClient.java
@@ -0,0 +1,258 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+import java.io.IOException;
+
+/**
+ * This interface represents only the most basic contract for HTTP request
+ * execution. It imposes no restrictions or particular details on the request
+ * execution process and leaves the specifics of state management,
+ * authentication and redirect handling up to individual implementations.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+public interface HttpClient {
+
+
+ /**
+ * Obtains the parameters for this client.
+ * These parameters will become defaults for all requests being
+ * executed with this client, and for the parameters of
+ * dependent objects in this client.
+ *
+ * @return the default parameters
+ *
+ * @deprecated (4.3) use
+ * {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
+ */
+ @Deprecated
+ HttpParams getParams();
+
+ /**
+ * Obtains the connection manager used by this client.
+ *
+ * @return the connection manager
+ *
+ * @deprecated (4.3) use
+ * {@link ch.boye.httpclientandroidlib.impl.client.HttpClientBuilder}.
+ */
+ @Deprecated
+ ClientConnectionManager getConnectionManager();
+
+ /**
+ * Executes HTTP request using the default context.
+ *
+ * @param request the request to execute
+ *
+ * @return the response to the request. This is always a final response,
+ * never an intermediate response with an 1xx status code.
+ * Whether redirects or authentication challenges will be returned
+ * or handled automatically depends on the implementation and
+ * configuration of this client.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ HttpResponse execute(HttpUriRequest request)
+ throws IOException, ClientProtocolException;
+
+ /**
+ * Executes HTTP request using the given context.
+ *
+ * @param request the request to execute
+ * @param context the context to use for the execution, or
+ * <code>null</code> to use the default context
+ *
+ * @return the response to the request. This is always a final response,
+ * never an intermediate response with an 1xx status code.
+ * Whether redirects or authentication challenges will be returned
+ * or handled automatically depends on the implementation and
+ * configuration of this client.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ HttpResponse execute(HttpUriRequest request, HttpContext context)
+ throws IOException, ClientProtocolException;
+
+ /**
+ * Executes HTTP request using the default context.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ *
+ * @return the response to the request. This is always a final response,
+ * never an intermediate response with an 1xx status code.
+ * Whether redirects or authentication challenges will be returned
+ * or handled automatically depends on the implementation and
+ * configuration of this client.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ HttpResponse execute(HttpHost target, HttpRequest request)
+ throws IOException, ClientProtocolException;
+
+ /**
+ * Executes HTTP request using the given context.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param context the context to use for the execution, or
+ * <code>null</code> to use the default context
+ *
+ * @return the response to the request. This is always a final response,
+ * never an intermediate response with an 1xx status code.
+ * Whether redirects or authentication challenges will be returned
+ * or handled automatically depends on the implementation and
+ * configuration of this client.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ HttpResponse execute(HttpHost target, HttpRequest request,
+ HttpContext context)
+ throws IOException, ClientProtocolException;
+
+ /**
+ * Executes HTTP request using the default context and processes the
+ * response using the given response handler.
+ * <p/>
+ * Implementing classes are required to ensure that the content entity
+ * associated with the response is fully consumed and the underlying
+ * connection is released back to the connection manager automatically
+ * in all cases relieving individual {@link ResponseHandler}s from
+ * having to manage resource deallocation internally.
+ *
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ <T> T execute(
+ HttpUriRequest request,
+ ResponseHandler<? extends T> responseHandler)
+ throws IOException, ClientProtocolException;
+
+ /**
+ * Executes HTTP request using the given context and processes the
+ * response using the given response handler.
+ * <p/>
+ * Implementing classes are required to ensure that the content entity
+ * associated with the response is fully consumed and the underlying
+ * connection is released back to the connection manager automatically
+ * in all cases relieving individual {@link ResponseHandler}s from
+ * having to manage resource deallocation internally.
+ *
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ * @param context the context to use for the execution, or
+ * <code>null</code> to use the default context
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ <T> T execute(
+ HttpUriRequest request,
+ ResponseHandler<? extends T> responseHandler,
+ HttpContext context)
+ throws IOException, ClientProtocolException;
+
+ /**
+ * Executes HTTP request to the target using the default context and
+ * processes the response using the given response handler.
+ * <p/>
+ * Implementing classes are required to ensure that the content entity
+ * associated with the response is fully consumed and the underlying
+ * connection is released back to the connection manager automatically
+ * in all cases relieving individual {@link ResponseHandler}s from
+ * having to manage resource deallocation internally.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ <T> T execute(
+ HttpHost target,
+ HttpRequest request,
+ ResponseHandler<? extends T> responseHandler)
+ throws IOException, ClientProtocolException;
+
+ /**
+ * Executes HTTP request to the target using the given context and
+ * processes the response using the given response handler.
+ * <p/>
+ * Implementing classes are required to ensure that the content entity
+ * associated with the response is fully consumed and the underlying
+ * connection is released back to the connection manager automatically
+ * in all cases relieving individual {@link ResponseHandler}s from
+ * having to manage resource deallocation internally.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ * @param context the context to use for the execution, or
+ * <code>null</code> to use the default context
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ <T> T execute(
+ HttpHost target,
+ HttpRequest request,
+ ResponseHandler<? extends T> responseHandler,
+ HttpContext context)
+ throws IOException, ClientProtocolException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpRequestRetryHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpRequestRetryHandler.java
new file mode 100644
index 000000000..8bbb11c49
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpRequestRetryHandler.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A handler for determining if an HttpRequest should be retried after a
+ * recoverable exception during execution.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ */
+public interface HttpRequestRetryHandler {
+
+ /**
+ * Determines if a method should be retried after an IOException
+ * occurs during execution.
+ *
+ * @param exception the exception that occurred
+ * @param executionCount the number of times this method has been
+ * unsuccessfully executed
+ * @param context the context for the request execution
+ *
+ * @return <code>true</code> if the method should be retried, <code>false</code>
+ * otherwise
+ */
+ boolean retryRequest(IOException exception, int executionCount, HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpResponseException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpResponseException.java
new file mode 100644
index 000000000..68500c6ac
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/HttpResponseException.java
@@ -0,0 +1,52 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals a non 2xx HTTP response.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class HttpResponseException extends ClientProtocolException {
+
+ private static final long serialVersionUID = -7186627969477257933L;
+
+ private final int statusCode;
+
+ public HttpResponseException(final int statusCode, final String s) {
+ super(s);
+ this.statusCode = statusCode;
+ }
+
+ public int getStatusCode() {
+ return this.statusCode;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/NonRepeatableRequestException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/NonRepeatableRequestException.java
new file mode 100644
index 000000000..6d9dce208
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/NonRepeatableRequestException.java
@@ -0,0 +1,72 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals failure to retry the request due to non-repeatable request
+ * entity.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class NonRepeatableRequestException extends ProtocolException {
+
+ private static final long serialVersionUID = 82685265288806048L;
+
+ /**
+ * Creates a new NonRepeatableEntityException with a <tt>null</tt> detail message.
+ */
+ public NonRepeatableRequestException() {
+ super();
+ }
+
+ /**
+ * Creates a new NonRepeatableEntityException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public NonRepeatableRequestException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new NonRepeatableEntityException with the specified detail message.
+ *
+ * @param message The exception detail message
+ * @param cause the cause
+ */
+ public NonRepeatableRequestException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectException.java
new file mode 100644
index 000000000..e187db789
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectException.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals violation of HTTP specification caused by an invalid redirect
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RedirectException extends ProtocolException {
+
+ private static final long serialVersionUID = 4418824536372559326L;
+
+ /**
+ * Creates a new RedirectException with a <tt>null</tt> detail message.
+ */
+ public RedirectException() {
+ super();
+ }
+
+ /**
+ * Creates a new RedirectException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public RedirectException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new RedirectException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public RedirectException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectHandler.java
new file mode 100644
index 000000000..f2dcd842b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectHandler.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A handler for determining if an HTTP request should be redirected to
+ * a new location in response to an HTTP response received from the target
+ * server.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use {@link RedirectStrategy}
+ */
+@Deprecated
+public interface RedirectHandler {
+
+ /**
+ * Determines if a request should be redirected to a new location
+ * given the response from the target server.
+ *
+ * @param response the response received from the target server
+ * @param context the context for the request execution
+ *
+ * @return <code>true</code> if the request should be redirected, <code>false</code>
+ * otherwise
+ */
+ boolean isRedirectRequested(HttpResponse response, HttpContext context);
+
+ /**
+ * Determines the location request is expected to be redirected to
+ * given the response from the target server and the current request
+ * execution context.
+ *
+ * @param response the response received from the target server
+ * @param context the context for the request execution
+ *
+ * @return redirect URI
+ */
+ URI getLocationURI(HttpResponse response, HttpContext context)
+ throws ProtocolException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectStrategy.java
new file mode 100644
index 000000000..ad2499c37
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RedirectStrategy.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A strategy for determining if an HTTP request should be redirected to
+ * a new location in response to an HTTP response received from the target
+ * server.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.1
+ */
+public interface RedirectStrategy {
+
+ /**
+ * Determines if a request should be redirected to a new location
+ * given the response from the target server.
+ *
+ * @param request the executed request
+ * @param response the response received from the target server
+ * @param context the context for the request execution
+ *
+ * @return <code>true</code> if the request should be redirected, <code>false</code>
+ * otherwise
+ */
+ boolean isRedirected(
+ HttpRequest request,
+ HttpResponse response,
+ HttpContext context) throws ProtocolException;
+
+ /**
+ * Determines the redirect location given the response from the target
+ * server and the current request execution context and generates a new
+ * request to be sent to the location.
+ *
+ * @param request the executed request
+ * @param response the response received from the target server
+ * @param context the context for the request execution
+ *
+ * @return redirected request
+ */
+ HttpUriRequest getRedirect(
+ HttpRequest request,
+ HttpResponse response,
+ HttpContext context) throws ProtocolException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RequestDirector.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RequestDirector.java
new file mode 100644
index 000000000..ebaeb74a0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/RequestDirector.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A client-side request director.
+ * The director decides which steps are necessary to execute a request.
+ * It establishes connections and optionally processes redirects and
+ * authentication challenges. The director may therefore generate and
+ * send a sequence of requests in order to execute one initial request.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) No longer used
+ */
+@Deprecated
+public interface RequestDirector {
+
+
+ /**
+ * Executes a request.
+ * <br/><b>Note:</b>
+ * For the time being, a new director is instantiated for each request.
+ * This is the same behavior as for <code>HttpMethodDirector</code>
+ * in HttpClient 3.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param context the context for executing the request
+ *
+ * @return the final response to the request.
+ * This is never an intermediate response with status code 1xx.
+ *
+ * @throws HttpException in case of a problem
+ * @throws IOException in case of an IO problem
+ * or if the connection was aborted
+ */
+ HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context)
+ throws HttpException, IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ResponseHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ResponseHandler.java
new file mode 100644
index 000000000..6fa02b650
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ResponseHandler.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+/**
+ * Handler that encapsulates the process of generating a response object
+ * from a {@link HttpResponse}.
+ *
+ *
+ * @since 4.0
+ */
+public interface ResponseHandler<T> {
+
+ /**
+ * Processes an {@link HttpResponse} and returns some value
+ * corresponding to that response.
+ *
+ * @param response The response to process
+ * @return A value determined by the response
+ *
+ * @throws ClientProtocolException in case of an http protocol error
+ * @throws IOException in case of a problem or the connection was aborted
+ */
+ T handleResponse(HttpResponse response) throws ClientProtocolException, IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ServiceUnavailableRetryStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ServiceUnavailableRetryStrategy.java
new file mode 100644
index 000000000..7a08dab65
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/ServiceUnavailableRetryStrategy.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Strategy interface that allows API users to plug in their own logic to
+ * control whether or not a retry should automatically be done, how many times
+ * it should be retried and so on.
+ *
+ * @since 4.2
+ */
+public interface ServiceUnavailableRetryStrategy {
+
+ /**
+ * Determines if a method should be retried given the response from the target server.
+ *
+ * @param response the response from the target server
+ * @param executionCount the number of times this method has been
+ * unsuccessfully executed
+ * @param context the context for the request execution
+
+ * @return <code>true</code> if the method should be retried, <code>false</code>
+ * otherwise
+ */
+ boolean retryRequest(HttpResponse response, int executionCount, HttpContext context);
+
+ /**
+ * @return The interval between the subsequent auto-retries.
+ */
+ long getRetryInterval();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/UserTokenHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/UserTokenHandler.java
new file mode 100644
index 000000000..1e15ef7c6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/UserTokenHandler.java
@@ -0,0 +1,58 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A handler for determining if the given execution context is user specific
+ * or not. The token object returned by this handler is expected to uniquely
+ * identify the current user if the context is user specific or to be
+ * <code>null</code> if the context does not contain any resources or details
+ * specific to the current user.
+ * <p/>
+ * The user token will be used to ensure that user specific resources will not
+ * be shared with or reused by other users.
+ *
+ * @since 4.0
+ */
+public interface UserTokenHandler {
+
+ /**
+ * The token object returned by this method is expected to uniquely
+ * identify the current user if the context is user specific or to be
+ * <code>null</code> if it is not.
+ *
+ * @param context the execution context
+ *
+ * @return user token that uniquely identifies the user or
+ * <code>null</null> if the context is not user specific.
+ */
+ Object getUserToken(HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/CacheResponseStatus.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/CacheResponseStatus.java
new file mode 100644
index 000000000..d000839af
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/CacheResponseStatus.java
@@ -0,0 +1,55 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+/**
+ * This enumeration represents the various ways a response can be generated
+ * by the {@link ch.boye.httpclientandroidlib.impl.client.cache.CachingHttpClient};
+ * if a request is executed with an {@link ch.boye.httpclientandroidlib.protocol.HttpContext}
+ * then a parameter with one of these values will be registered in the
+ * context under the key
+ * {@link ch.boye.httpclientandroidlib.impl.client.cache.CachingHttpClient#CACHE_RESPONSE_STATUS}.
+ */
+public enum CacheResponseStatus {
+
+ /** The response was generated directly by the caching module. */
+ CACHE_MODULE_RESPONSE,
+
+ /** A response was generated from the cache with no requests sent
+ * upstream.
+ */
+ CACHE_HIT,
+
+ /** The response came from an upstream server. */
+ CACHE_MISS,
+
+ /** The response was generated from the cache after validating the
+ * entry with the origin server.
+ */
+ VALIDATED;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HeaderConstants.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HeaderConstants.java
new file mode 100644
index 000000000..22f34dcff
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HeaderConstants.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Records static constants for various HTTP header names.
+ * @since 4.1
+ */
+@Immutable
+public class HeaderConstants {
+
+ public static final String GET_METHOD = "GET";
+ public static final String HEAD_METHOD = "HEAD";
+ public static final String OPTIONS_METHOD = "OPTIONS";
+ public static final String PUT_METHOD = "PUT";
+ public static final String DELETE_METHOD = "DELETE";
+ public static final String TRACE_METHOD = "TRACE";
+
+ public static final String LAST_MODIFIED = "Last-Modified";
+ public static final String IF_MATCH = "If-Match";
+ public static final String IF_RANGE = "If-Range";
+ public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
+ public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+ public static final String IF_NONE_MATCH = "If-None-Match";
+
+ public static final String PRAGMA = "Pragma";
+ public static final String MAX_FORWARDS = "Max-Forwards";
+ public static final String ETAG = "ETag";
+ public static final String EXPIRES = "Expires";
+ public static final String AGE = "Age";
+ public static final String VARY = "Vary";
+ public static final String ALLOW = "Allow";
+ public static final String VIA = "Via";
+ public static final String PUBLIC = "public";
+ public static final String PRIVATE = "private";
+
+ public static final String CACHE_CONTROL = "Cache-Control";
+ public static final String CACHE_CONTROL_NO_STORE = "no-store";
+ public static final String CACHE_CONTROL_NO_CACHE = "no-cache";
+ public static final String CACHE_CONTROL_MAX_AGE = "max-age";
+ public static final String CACHE_CONTROL_MAX_STALE = "max-stale";
+ public static final String CACHE_CONTROL_MIN_FRESH = "min-fresh";
+ public static final String CACHE_CONTROL_MUST_REVALIDATE = "must-revalidate";
+ public static final String CACHE_CONTROL_PROXY_REVALIDATE = "proxy-revalidate";
+ public static final String STALE_IF_ERROR = "stale-if-error";
+ public static final String STALE_WHILE_REVALIDATE = "stale-while-revalidate";
+
+ public static final String WARNING = "Warning";
+ public static final String RANGE = "Range";
+ public static final String CONTENT_RANGE = "Content-Range";
+ public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
+ public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
+ public static final String AUTHORIZATION = "Authorization";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheContext.java
new file mode 100644
index 000000000..54edfa12a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheContext.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * @since 4.3
+ */
+@NotThreadSafe
+public class HttpCacheContext extends HttpClientContext {
+
+ /**
+ * This is the name under which the {@link CacheResponseStatus} of a request
+ * (for example, whether it resulted in a cache hit) will be recorded if an
+ * {@link HttpContext} is provided during execution.
+ */
+ public static final String CACHE_RESPONSE_STATUS = "http.cache.response.status";
+
+ public static HttpCacheContext adapt(final HttpContext context) {
+ if (context instanceof HttpCacheContext) {
+ return (HttpCacheContext) context;
+ } else {
+ return new HttpCacheContext(context);
+ }
+ }
+
+ public static HttpCacheContext create() {
+ return new HttpCacheContext(new BasicHttpContext());
+ }
+
+ public HttpCacheContext(final HttpContext context) {
+ super(context);
+ }
+
+ public HttpCacheContext() {
+ super();
+ }
+
+ public CacheResponseStatus getCacheResponseStatus() {
+ return getAttribute(CACHE_RESPONSE_STATUS, CacheResponseStatus.class);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntry.java
new file mode 100644
index 000000000..d03786279
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntry.java
@@ -0,0 +1,263 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.message.HeaderGroup;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Structure used to store an {@link ch.boye.httpclientandroidlib.HttpResponse} in a cache.
+ * Some entries can optionally depend on system resources that may require
+ * explicit deallocation. In such a case {@link #getResource()} should return
+ * a non null instance of {@link Resource} that must be deallocated by calling
+ * {@link Resource#dispose()} method when no longer used.
+ *
+ * @since 4.1
+ */
+@Immutable
+public class HttpCacheEntry implements Serializable {
+
+ private static final long serialVersionUID = -6300496422359477413L;
+
+ private final Date requestDate;
+ private final Date responseDate;
+ private final StatusLine statusLine;
+ private final HeaderGroup responseHeaders;
+ private final Resource resource;
+ private final Map<String,String> variantMap;
+ private final Date date;
+
+ /**
+ * Create a new {@link HttpCacheEntry} with variants.
+ * @param requestDate
+ * Date/time when the request was made (Used for age
+ * calculations)
+ * @param responseDate
+ * Date/time that the response came back (Used for age
+ * calculations)
+ * @param statusLine
+ * HTTP status line from origin response
+ * @param responseHeaders
+ * Header[] from original HTTP Response
+ * @param resource representing origin response body
+ * @param variantMap describing cache entries that are variants
+ * of this parent entry; this maps a "variant key" (derived
+ * from the varying request headers) to a "cache key" (where
+ * in the cache storage the particular variant is located)
+ */
+ public HttpCacheEntry(
+ final Date requestDate,
+ final Date responseDate,
+ final StatusLine statusLine,
+ final Header[] responseHeaders,
+ final Resource resource,
+ final Map<String,String> variantMap) {
+ super();
+ Args.notNull(requestDate, "Request date");
+ Args.notNull(responseDate, "Response date");
+ Args.notNull(statusLine, "Status line");
+ Args.notNull(responseHeaders, "Response headers");
+ this.requestDate = requestDate;
+ this.responseDate = responseDate;
+ this.statusLine = statusLine;
+ this.responseHeaders = new HeaderGroup();
+ this.responseHeaders.setHeaders(responseHeaders);
+ this.resource = resource;
+ this.variantMap = variantMap != null
+ ? new HashMap<String,String>(variantMap)
+ : null;
+ this.date = parseDate();
+ }
+
+ /**
+ * Create a new {@link HttpCacheEntry}.
+ *
+ * @param requestDate
+ * Date/time when the request was made (Used for age
+ * calculations)
+ * @param responseDate
+ * Date/time that the response came back (Used for age
+ * calculations)
+ * @param statusLine
+ * HTTP status line from origin response
+ * @param responseHeaders
+ * Header[] from original HTTP Response
+ * @param resource representing origin response body
+ */
+ public HttpCacheEntry(final Date requestDate, final Date responseDate, final StatusLine statusLine,
+ final Header[] responseHeaders, final Resource resource) {
+ this(requestDate, responseDate, statusLine, responseHeaders, resource,
+ new HashMap<String,String>());
+ }
+
+ /**
+ * Find the "Date" response header and parse it into a java.util.Date
+ * @return the Date value of the header or null if the header is not present
+ */
+ private Date parseDate() {
+ final Header dateHdr = getFirstHeader(HTTP.DATE_HEADER);
+ if (dateHdr == null) {
+ return null;
+ }
+ return DateUtils.parseDate(dateHdr.getValue());
+ }
+
+ /**
+ * Returns the {@link StatusLine} from the origin
+ * {@link ch.boye.httpclientandroidlib.HttpResponse}.
+ */
+ public StatusLine getStatusLine() {
+ return this.statusLine;
+ }
+
+ /**
+ * Returns the {@link ProtocolVersion} from the origin
+ * {@link ch.boye.httpclientandroidlib.HttpResponse}.
+ */
+ public ProtocolVersion getProtocolVersion() {
+ return this.statusLine.getProtocolVersion();
+ }
+
+ /**
+ * Gets the reason phrase from the origin
+ * {@link ch.boye.httpclientandroidlib.HttpResponse}, for example, "Not Modified".
+ */
+ public String getReasonPhrase() {
+ return this.statusLine.getReasonPhrase();
+ }
+
+ /**
+ * Returns the HTTP response code from the origin
+ * {@link ch.boye.httpclientandroidlib.HttpResponse}.
+ */
+ public int getStatusCode() {
+ return this.statusLine.getStatusCode();
+ }
+
+ /**
+ * Returns the time the associated origin request was initiated by the
+ * caching module.
+ * @return {@link Date}
+ */
+ public Date getRequestDate() {
+ return requestDate;
+ }
+
+ /**
+ * Returns the time the origin response was received by the caching module.
+ * @return {@link Date}
+ */
+ public Date getResponseDate() {
+ return responseDate;
+ }
+
+ /**
+ * Returns all the headers that were on the origin response.
+ */
+ public Header[] getAllHeaders() {
+ return responseHeaders.getAllHeaders();
+ }
+
+ /**
+ * Returns the first header from the origin response with the given
+ * name.
+ */
+ public Header getFirstHeader(final String name) {
+ return responseHeaders.getFirstHeader(name);
+ }
+
+ /**
+ * Gets all the headers with the given name that were on the origin
+ * response.
+ */
+ public Header[] getHeaders(final String name) {
+ return responseHeaders.getHeaders(name);
+ }
+
+ /**
+ * Gets the Date value of the "Date" header or null if the header is missing or cannot be
+ * parsed.
+ *
+ * @since 4.3
+ */
+ public Date getDate() {
+ return date;
+ }
+
+ /**
+ * Returns the {@link Resource} containing the origin response body.
+ */
+ public Resource getResource() {
+ return this.resource;
+ }
+
+ /**
+ * Indicates whether the origin response indicated the associated
+ * resource had variants (i.e. that the Vary header was set on the
+ * origin response).
+ * @return {@code true} if this cached response was a variant
+ */
+ public boolean hasVariants() {
+ return getFirstHeader(HeaderConstants.VARY) != null;
+ }
+
+ /**
+ * Returns an index about where in the cache different variants for
+ * a given resource are stored. This maps "variant keys" to "cache keys",
+ * where the variant key is derived from the varying request headers,
+ * and the cache key is the location in the
+ * {@link ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage} where that
+ * particular variant is stored. The first variant returned is used as
+ * the "parent" entry to hold this index of the other variants.
+ */
+ public Map<String, String> getVariantMap() {
+ return Collections.unmodifiableMap(variantMap);
+ }
+
+ /**
+ * Provides a string representation of this instance suitable for
+ * human consumption.
+ */
+ @Override
+ public String toString() {
+ return "[request date=" + this.requestDate + "; response date=" + this.responseDate
+ + "; statusLine=" + this.statusLine + "]";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializationException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializationException.java
new file mode 100644
index 000000000..e74f64db6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializationException.java
@@ -0,0 +1,48 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import java.io.IOException;
+
+/**
+ * Thrown if serialization or deserialization of an {@link HttpCacheEntry}
+ * fails.
+ */
+public class HttpCacheEntrySerializationException extends IOException {
+
+ private static final long serialVersionUID = 9219188365878433519L;
+
+ public HttpCacheEntrySerializationException(final String message) {
+ super();
+ }
+
+ public HttpCacheEntrySerializationException(final String message, final Throwable cause) {
+ super(message);
+ initCause(cause);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializer.java
new file mode 100644
index 000000000..2903fb74d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheEntrySerializer.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Used by some {@link HttpCacheStorage} implementations to serialize
+ * {@link HttpCacheEntry} instances to a byte representation before
+ * storage.
+ */
+public interface HttpCacheEntrySerializer {
+
+ /**
+ * Serializes the given entry to a byte representation on the
+ * given {@link OutputStream}.
+ * @throws IOException
+ */
+ void writeTo(HttpCacheEntry entry, OutputStream os) throws IOException;
+
+ /**
+ * Deserializes a byte representation of a cache entry by reading
+ * from the given {@link InputStream}.
+ * @throws IOException
+ */
+ HttpCacheEntry readFrom(InputStream is) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheInvalidator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheInvalidator.java
new file mode 100644
index 000000000..f8e70968b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheInvalidator.java
@@ -0,0 +1,58 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+/**
+ * Given a particular HttpRequest, flush any cache entries that this request
+ * would invalidate.
+ *
+ * @since 4.3
+ */
+public interface HttpCacheInvalidator {
+
+ /**
+ * Remove cache entries from the cache that are no longer fresh or have been
+ * invalidated in some way.
+ *
+ * @param host
+ * The backend host we are talking to
+ * @param req
+ * The HttpRequest to that host
+ */
+ void flushInvalidatedCacheEntries(HttpHost host, HttpRequest req);
+
+ /**
+ * Flushes entries that were invalidated by the given response received for
+ * the given host/request pair.
+ */
+ void flushInvalidatedCacheEntries(HttpHost host, HttpRequest request, HttpResponse response);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheStorage.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheStorage.java
new file mode 100644
index 000000000..b0759d195
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheStorage.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import java.io.IOException;
+
+/**
+ * New storage backends should implement this {@link HttpCacheStorage}
+ * interface. They can then be plugged into the existing
+ * {@link ch.boye.httpclientandroidlib.impl.client.cache.CachingHttpClient}
+ * implementation.
+ *
+ * @since 4.1
+ */
+public interface HttpCacheStorage {
+
+ /**
+ * Store a given cache entry under the given key.
+ * @param key where in the cache to store the entry
+ * @param entry cached response to store
+ * @throws IOException
+ */
+ void putEntry(String key, HttpCacheEntry entry) throws IOException;
+
+ /**
+ * Retrieves the cache entry stored under the given key
+ * or null if no entry exists under that key.
+ * @param key cache key
+ * @return an {@link HttpCacheEntry} or {@code null} if no
+ * entry exists
+ * @throws IOException
+ */
+ HttpCacheEntry getEntry(String key) throws IOException;
+
+ /**
+ * Deletes/invalidates/removes any cache entries currently
+ * stored under the given key.
+ * @param key
+ * @throws IOException
+ */
+ void removeEntry(String key) throws IOException;
+
+ /**
+ * Atomically applies the given callback to update an existing cache
+ * entry under a given key.
+ * @param key indicates which entry to modify
+ * @param callback performs the update; see
+ * {@link HttpCacheUpdateCallback} for details, but roughly the
+ * callback expects to be handed the current entry and will return
+ * the new value for the entry.
+ * @throws IOException
+ * @throws HttpCacheUpdateException
+ */
+ void updateEntry(
+ String key, HttpCacheUpdateCallback callback) throws IOException, HttpCacheUpdateException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateCallback.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateCallback.java
new file mode 100644
index 000000000..abc810fe8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateCallback.java
@@ -0,0 +1,52 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import java.io.IOException;
+
+/**
+ * Used for atomically updating entries in a {@link HttpCacheStorage}
+ * implementation. The current entry (if any) is fed into an implementation
+ * of this interface, and the new, possibly updated entry (if any)
+ * should be returned.
+ */
+public interface HttpCacheUpdateCallback {
+
+ /**
+ * Returns the new cache entry that should replace an existing one.
+ *
+ * @param existing
+ * the cache entry currently in-place in the cache, possibly
+ * <code>null</code> if nonexistent
+ * @return the cache entry that should replace it, again,
+ * possibly <code>null</code> if the entry should be deleted
+ *
+ * @since 4.1
+ */
+ HttpCacheEntry update(HttpCacheEntry existing) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateException.java
new file mode 100644
index 000000000..278fe3afb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/HttpCacheUpdateException.java
@@ -0,0 +1,48 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+/**
+ * Signals that {@link HttpCacheStorage} encountered an error performing an
+ * update operation.
+ *
+ * @since 4.1
+ */
+public class HttpCacheUpdateException extends Exception {
+
+ private static final long serialVersionUID = 823573584868632876L;
+
+ public HttpCacheUpdateException(final String message) {
+ super(message);
+ }
+
+ public HttpCacheUpdateException(final String message, final Throwable cause) {
+ super(message);
+ initCause(cause);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/InputLimit.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/InputLimit.java
new file mode 100644
index 000000000..45ef3b26d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/InputLimit.java
@@ -0,0 +1,76 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * Used to limiting the size of an incoming response body of
+ * unknown size that is optimistically being read in anticipation
+ * of caching it.
+ * @since 4.1
+ */
+@NotThreadSafe // reached
+public class InputLimit {
+
+ private final long value;
+ private boolean reached;
+
+ /**
+ * Create a limit for how many bytes of a response body to
+ * read.
+ * @param value maximum length in bytes
+ */
+ public InputLimit(final long value) {
+ super();
+ this.value = value;
+ this.reached = false;
+ }
+
+ /**
+ * Returns the current maximum limit that was set on
+ * creation.
+ */
+ public long getValue() {
+ return this.value;
+ }
+
+ /**
+ * Used to report that the limit has been reached.
+ */
+ public void reached() {
+ this.reached = true;
+ }
+
+ /**
+ * Returns {@code true} if the input limit has been reached.
+ */
+ public boolean isReached() {
+ return this.reached;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/Resource.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/Resource.java
new file mode 100644
index 000000000..86811e85c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/Resource.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+
+/**
+ * Represents a disposable system resource used for handling
+ * cached response bodies.
+ *
+ * @since 4.1
+ */
+public interface Resource extends Serializable {
+
+ /**
+ * Returns an {@link InputStream} from which the response
+ * body can be read.
+ * @throws IOException
+ */
+ InputStream getInputStream() throws IOException;
+
+ /**
+ * Returns the length in bytes of the response body.
+ */
+ long length();
+
+ /**
+ * Indicates the system no longer needs to keep this
+ * response body and any system resources associated with
+ * it may be reclaimed.
+ */
+ void dispose();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/ResourceFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/ResourceFactory.java
new file mode 100644
index 000000000..0583d2605
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/ResourceFactory.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.cache;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Generates {@link Resource} instances for handling cached
+ * HTTP response bodies.
+ *
+ * @since 4.1
+ */
+public interface ResourceFactory {
+
+ /**
+ * Creates a {@link Resource} from a given response body.
+ * @param requestId a unique identifier for this particular
+ * response body
+ * @param instream the original {@link InputStream}
+ * containing the response body of the origin HTTP response.
+ * @param limit maximum number of bytes to consume of the
+ * response body; if this limit is reached before the
+ * response body is fully consumed, mark the limit has
+ * having been reached and return a {@code Resource}
+ * containing the data read to that point.
+ * @return a {@code Resource} containing however much of
+ * the response body was successfully read.
+ * @throws IOException
+ */
+ Resource generate(String requestId, InputStream instream, InputLimit limit) throws IOException;
+
+ /**
+ * Clones an existing {@link Resource}.
+ * @param requestId unique identifier provided to associate
+ * with the cloned response body.
+ * @param resource the original response body to clone.
+ * @return the {@code Resource} copy
+ * @throws IOException
+ */
+ Resource copy(String requestId, Resource resource) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/package.html b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/package.html
new file mode 100644
index 000000000..58a1e3ff3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/cache/package.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+====================================================================
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+====================================================================
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the Apache Software Foundation. For more
+information on the Apache Software Foundation, please see
+<http://www.apache.org/>.
+-->
+</head>
+<body bgcolor="white">
+
+<p>
+This package consists largely of constants and interfaces that are
+necessary for building new storage backends for the
+{@link org.apache.http.impl.client.cache.CachingHttpClient} or for
+those clients wanting to get a little more behavioral information
+out of the cache module (for example, whether a particular response
+was a cache hit or not). Developers that simply want to instantiate
+and make use of the caching module will be better off looking at
+the {@code CachingHttpClient} documentation itself.
+</p>
+<p>
+The classes in this package can be divided into two main groups:
+reference constants and interfaces needed for storage backends. In
+the former group,
+{@link org.apache.http.client.cache.HeaderConstants} contains a list
+of HTTP header names encoded as static fields, and the
+{@link org.apache.http.client.cache.CacheResponseStatus} enumeration
+values are set in an {@link org.apache.http.protocol.HttpContext} by
+the {@code CachingHttpClient} to indicate how the request was
+processed by the caching module itself.
+</p>
+<p>
+New storage backends will need to implement the
+{@link org.apache.http.client.cache.HttpCacheStorage}
+interface; they can then be passed to one of the {@code CachingHttpClient}
+constructors, which will happily make use of the new storage mechanism.
+The {@link org.apache.http.client.cache.HttpCacheEntry} class shows the
+datastructure for a cache entry that must be stored by the
+{@code HttpCacheStorage}.
+There is, in addition, the notion of a
+{@link org.apache.http.client.cache.Resource} and an associated
+{@link org.apache.http.client.cache.ResourceFactory}, which are used for
+managing the handling of cached response bodies. The default implementation
+used by the {@code CachingHttpClient} stores response bodies in memory;
+alternative implementations might involve storing these in a filesystem. A new
+{@code ResourceFactory} can be provided along with a {@code HttpCacheStorage}
+in one of the constructors to the {@code CachingHttpClient}. Finally, some
+of the additional storage backends we provide, like the
+{@link org.apache.http.impl.client.cache.ehcache.EhcacheHttpCacheStorage} and
+{@link org.apache.http.impl.client.cache.memcached.MemcachedHttpCacheStorage},
+can be provided with different serializers for the cache entry metadata;
+developers wanting to experiment with different serialization techniques
+should implement the
+{@link org.apache.http.client.cache.HttpCacheEntrySerializer} interface.
+</p>
+</body>
+</html>
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/AuthSchemes.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/AuthSchemes.java
new file mode 100644
index 000000000..a8b4db5e0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/AuthSchemes.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.config;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Standard authentication schemes supported by HttpClient.
+ *
+ * @since 4.3
+ */
+@Immutable
+public final class AuthSchemes {
+
+ /**
+ * Basic authentication scheme as defined in RFC2617 (considered inherently
+ * insecure, but most widely supported)
+ */
+ public static final String BASIC = "Basic";
+
+ /**
+ * Digest authentication scheme as defined in RFC2617.
+ */
+ public static final String DIGEST = "Digest";
+
+ /**
+ * The NTLM scheme is a proprietary Microsoft Windows Authentication
+ * protocol (considered to be the most secure among currently supported
+ * authentication schemes).
+ */
+ public static final String NTLM = "NTLM";
+
+ /**
+ * SPNEGO Authentication scheme.
+ */
+ public static final String SPNEGO = "negotiate";
+
+ /**
+ * Kerberos Authentication scheme.
+ */
+ public static final String KERBEROS = "Kerberos";
+
+ private AuthSchemes() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/CookieSpecs.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/CookieSpecs.java
new file mode 100644
index 000000000..132c6606f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/CookieSpecs.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.config;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Standard cookie specifications supported by HttpClient.
+ *
+ * @since 4.3
+ */
+@Immutable
+public final class CookieSpecs {
+
+ /**
+ * The policy that provides high degree of compatibility
+ * with common cookie management of popular HTTP agents.
+ */
+ public static final String BROWSER_COMPATIBILITY = "compatibility";
+
+ /**
+ * The Netscape cookie draft compliant policy.
+ */
+ public static final String NETSCAPE = "netscape";
+
+ /**
+ * The RFC 2965 compliant policy (standard).
+ */
+ public static final String STANDARD = "standard";
+
+ /**
+ * The default 'best match' policy.
+ */
+ public static final String BEST_MATCH = "best-match";
+
+ /**
+ * The policy that ignores cookies.
+ */
+ public static final String IGNORE_COOKIES = "ignoreCookies";
+
+ private CookieSpecs() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/RequestConfig.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/RequestConfig.java
new file mode 100644
index 000000000..e861f5e68
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/RequestConfig.java
@@ -0,0 +1,442 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.config;
+
+import java.net.InetAddress;
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+
+public class RequestConfig implements Cloneable {
+
+ public static final RequestConfig DEFAULT = new Builder().build();
+
+ private final boolean expectContinueEnabled;
+ private final HttpHost proxy;
+ private final InetAddress localAddress;
+ private final boolean staleConnectionCheckEnabled;
+ private final String cookieSpec;
+ private final boolean redirectsEnabled;
+ private final boolean relativeRedirectsAllowed;
+ private final boolean circularRedirectsAllowed;
+ private final int maxRedirects;
+ private final boolean authenticationEnabled;
+ private final Collection<String> targetPreferredAuthSchemes;
+ private final Collection<String> proxyPreferredAuthSchemes;
+ private final int connectionRequestTimeout;
+ private final int connectTimeout;
+ private final int socketTimeout;
+
+ RequestConfig(
+ final boolean expectContinueEnabled,
+ final HttpHost proxy,
+ final InetAddress localAddress,
+ final boolean staleConnectionCheckEnabled,
+ final String cookieSpec,
+ final boolean redirectsEnabled,
+ final boolean relativeRedirectsAllowed,
+ final boolean circularRedirectsAllowed,
+ final int maxRedirects,
+ final boolean authenticationEnabled,
+ final Collection<String> targetPreferredAuthSchemes,
+ final Collection<String> proxyPreferredAuthSchemes,
+ final int connectionRequestTimeout,
+ final int connectTimeout,
+ final int socketTimeout) {
+ super();
+ this.expectContinueEnabled = expectContinueEnabled;
+ this.proxy = proxy;
+ this.localAddress = localAddress;
+ this.staleConnectionCheckEnabled = staleConnectionCheckEnabled;
+ this.cookieSpec = cookieSpec;
+ this.redirectsEnabled = redirectsEnabled;
+ this.relativeRedirectsAllowed = relativeRedirectsAllowed;
+ this.circularRedirectsAllowed = circularRedirectsAllowed;
+ this.maxRedirects = maxRedirects;
+ this.authenticationEnabled = authenticationEnabled;
+ this.targetPreferredAuthSchemes = targetPreferredAuthSchemes;
+ this.proxyPreferredAuthSchemes = proxyPreferredAuthSchemes;
+ this.connectionRequestTimeout = connectionRequestTimeout;
+ this.connectTimeout = connectTimeout;
+ this.socketTimeout = socketTimeout;
+ }
+
+ /**
+ * Determines whether the 'Expect: 100-Continue' handshake is enabled
+ * for entity enclosing methods. The purpose of the 'Expect: 100-Continue'
+ * handshake is to allow a client that is sending a request message with
+ * a request body to determine if the origin server is willing to
+ * accept the request (based on the request headers) before the client
+ * sends the request body.
+ * <p/>
+ * The use of the 'Expect: 100-continue' handshake can result in
+ * a noticeable performance improvement for entity enclosing requests
+ * (such as POST and PUT) that require the target server's
+ * authentication.
+ * <p/>
+ * 'Expect: 100-continue' handshake should be used with caution, as it
+ * may cause problems with HTTP servers and proxies that do not support
+ * HTTP/1.1 protocol.
+ * <p/>
+ * Default: <code>false</code>
+ */
+ public boolean isExpectContinueEnabled() {
+ return expectContinueEnabled;
+ }
+
+ /**
+ * Returns HTTP proxy to be used for request execution.
+ * <p/>
+ * Default: <code>null</code>
+ */
+ public HttpHost getProxy() {
+ return proxy;
+ }
+
+ /**
+ * Returns local address to be used for request execution.
+ * <p/>
+ * On machines with multiple network interfaces, this parameter
+ * can be used to select the network interface from which the
+ * connection originates.
+ * <p/>
+ * Default: <code>null</code>
+ */
+ public InetAddress getLocalAddress() {
+ return localAddress;
+ }
+
+ /**
+ * Determines whether stale connection check is to be used. The stale
+ * connection check can cause up to 30 millisecond overhead per request and
+ * should be used only when appropriate. For performance critical
+ * operations this check should be disabled.
+ * <p/>
+ * Default: <code>true</code>
+ */
+ public boolean isStaleConnectionCheckEnabled() {
+ return staleConnectionCheckEnabled;
+ }
+
+ /**
+ * Determines the name of the cookie specification to be used for HTTP state
+ * management.
+ * <p/>
+ * Default: <code>null</code>
+ */
+ public String getCookieSpec() {
+ return cookieSpec;
+ }
+
+ /**
+ * Determines whether redirects should be handled automatically.
+ * <p/>
+ * Default: <code>true</code>
+ */
+ public boolean isRedirectsEnabled() {
+ return redirectsEnabled;
+ }
+
+ /**
+ * Determines whether relative redirects should be rejected. HTTP specification
+ * requires the location value be an absolute URI.
+ * <p/>
+ * Default: <code>true</code>
+ */
+ public boolean isRelativeRedirectsAllowed() {
+ return relativeRedirectsAllowed;
+ }
+
+ /**
+ * Determines whether circular redirects (redirects to the same location) should
+ * be allowed. The HTTP spec is not sufficiently clear whether circular redirects
+ * are permitted, therefore optionally they can be enabled
+ * <p/>
+ * Default: <code>false</code>
+ */
+ public boolean isCircularRedirectsAllowed() {
+ return circularRedirectsAllowed;
+ }
+
+ /**
+ * Returns the maximum number of redirects to be followed. The limit on number
+ * of redirects is intended to prevent infinite loops.
+ * <p/>
+ * Default: <code>50</code>
+ */
+ public int getMaxRedirects() {
+ return maxRedirects;
+ }
+
+ /**
+ * Determines whether authentication should be handled automatically.
+ * <p/>
+ * Default: <code>true</code>
+ */
+ public boolean isAuthenticationEnabled() {
+ return authenticationEnabled;
+ }
+
+ /**
+ * Determines the order of preference for supported authentication schemes
+ * when authenticating with the target host.
+ * <p/>
+ * Default: <code>null</code>
+ */
+ public Collection<String> getTargetPreferredAuthSchemes() {
+ return targetPreferredAuthSchemes;
+ }
+
+ /**
+ * Determines the order of preference for supported authentication schemes
+ * when authenticating with the proxy host.
+ * <p/>
+ * Default: <code>null</code>
+ */
+ public Collection<String> getProxyPreferredAuthSchemes() {
+ return proxyPreferredAuthSchemes;
+ }
+
+ /**
+ * Returns the timeout in milliseconds used when requesting a connection
+ * from the connection manager. A timeout value of zero is interpreted
+ * as an infinite timeout.
+ * <p/>
+ * A timeout value of zero is interpreted as an infinite timeout.
+ * A negative value is interpreted as undefined (system default).
+ * <p/>
+ * Default: <code>-1</code>
+ */
+ public int getConnectionRequestTimeout() {
+ return connectionRequestTimeout;
+ }
+
+ /**
+ * Determines the timeout in milliseconds until a connection is established.
+ * A timeout value of zero is interpreted as an infinite timeout.
+ * <p/>
+ * A timeout value of zero is interpreted as an infinite timeout.
+ * A negative value is interpreted as undefined (system default).
+ * <p/>
+ * Default: <code>-1</code>
+ */
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ /**
+ * Defines the socket timeout (<code>SO_TIMEOUT</code>) in milliseconds,
+ * which is the timeout for waiting for data or, put differently,
+ * a maximum period inactivity between two consecutive data packets).
+ * <p/>
+ * A timeout value of zero is interpreted as an infinite timeout.
+ * A negative value is interpreted as undefined (system default).
+ * <p/>
+ * Default: <code>-1</code>
+ */
+ public int getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ @Override
+ protected RequestConfig clone() throws CloneNotSupportedException {
+ return (RequestConfig) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(", expectContinueEnabled=").append(expectContinueEnabled);
+ builder.append(", proxy=").append(proxy);
+ builder.append(", localAddress=").append(localAddress);
+ builder.append(", staleConnectionCheckEnabled=").append(staleConnectionCheckEnabled);
+ builder.append(", cookieSpec=").append(cookieSpec);
+ builder.append(", redirectsEnabled=").append(redirectsEnabled);
+ builder.append(", relativeRedirectsAllowed=").append(relativeRedirectsAllowed);
+ builder.append(", maxRedirects=").append(maxRedirects);
+ builder.append(", circularRedirectsAllowed=").append(circularRedirectsAllowed);
+ builder.append(", authenticationEnabled=").append(authenticationEnabled);
+ builder.append(", targetPreferredAuthSchemes=").append(targetPreferredAuthSchemes);
+ builder.append(", proxyPreferredAuthSchemes=").append(proxyPreferredAuthSchemes);
+ builder.append(", connectionRequestTimeout=").append(connectionRequestTimeout);
+ builder.append(", connectTimeout=").append(connectTimeout);
+ builder.append(", socketTimeout=").append(socketTimeout);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static RequestConfig.Builder custom() {
+ return new Builder();
+ }
+
+ public static RequestConfig.Builder copy(final RequestConfig config) {
+ return new Builder()
+ .setExpectContinueEnabled(config.isExpectContinueEnabled())
+ .setProxy(config.getProxy())
+ .setLocalAddress(config.getLocalAddress())
+ .setStaleConnectionCheckEnabled(config.isStaleConnectionCheckEnabled())
+ .setCookieSpec(config.getCookieSpec())
+ .setRedirectsEnabled(config.isRedirectsEnabled())
+ .setRelativeRedirectsAllowed(config.isRelativeRedirectsAllowed())
+ .setCircularRedirectsAllowed(config.isCircularRedirectsAllowed())
+ .setMaxRedirects(config.getMaxRedirects())
+ .setAuthenticationEnabled(config.isAuthenticationEnabled())
+ .setTargetPreferredAuthSchemes(config.getTargetPreferredAuthSchemes())
+ .setProxyPreferredAuthSchemes(config.getProxyPreferredAuthSchemes())
+ .setConnectionRequestTimeout(config.getConnectionRequestTimeout())
+ .setConnectTimeout(config.getConnectTimeout())
+ .setSocketTimeout(config.getSocketTimeout());
+ }
+
+ public static class Builder {
+
+ private boolean expectContinueEnabled;
+ private HttpHost proxy;
+ private InetAddress localAddress;
+ private boolean staleConnectionCheckEnabled;
+ private String cookieSpec;
+ private boolean redirectsEnabled;
+ private boolean relativeRedirectsAllowed;
+ private boolean circularRedirectsAllowed;
+ private int maxRedirects;
+ private boolean authenticationEnabled;
+ private Collection<String> targetPreferredAuthSchemes;
+ private Collection<String> proxyPreferredAuthSchemes;
+ private int connectionRequestTimeout;
+ private int connectTimeout;
+ private int socketTimeout;
+
+ Builder() {
+ super();
+ this.staleConnectionCheckEnabled = true;
+ this.redirectsEnabled = true;
+ this.maxRedirects = 50;
+ this.relativeRedirectsAllowed = true;
+ this.authenticationEnabled = true;
+ this.connectionRequestTimeout = -1;
+ this.connectTimeout = -1;
+ this.socketTimeout = -1;
+ }
+
+ public Builder setExpectContinueEnabled(final boolean expectContinueEnabled) {
+ this.expectContinueEnabled = expectContinueEnabled;
+ return this;
+ }
+
+ public Builder setProxy(final HttpHost proxy) {
+ this.proxy = proxy;
+ return this;
+ }
+
+ public Builder setLocalAddress(final InetAddress localAddress) {
+ this.localAddress = localAddress;
+ return this;
+ }
+
+ public Builder setStaleConnectionCheckEnabled(final boolean staleConnectionCheckEnabled) {
+ this.staleConnectionCheckEnabled = staleConnectionCheckEnabled;
+ return this;
+ }
+
+ public Builder setCookieSpec(final String cookieSpec) {
+ this.cookieSpec = cookieSpec;
+ return this;
+ }
+
+ public Builder setRedirectsEnabled(final boolean redirectsEnabled) {
+ this.redirectsEnabled = redirectsEnabled;
+ return this;
+ }
+
+ public Builder setRelativeRedirectsAllowed(final boolean relativeRedirectsAllowed) {
+ this.relativeRedirectsAllowed = relativeRedirectsAllowed;
+ return this;
+ }
+
+ public Builder setCircularRedirectsAllowed(final boolean circularRedirectsAllowed) {
+ this.circularRedirectsAllowed = circularRedirectsAllowed;
+ return this;
+ }
+
+ public Builder setMaxRedirects(final int maxRedirects) {
+ this.maxRedirects = maxRedirects;
+ return this;
+ }
+
+ public Builder setAuthenticationEnabled(final boolean authenticationEnabled) {
+ this.authenticationEnabled = authenticationEnabled;
+ return this;
+ }
+
+ public Builder setTargetPreferredAuthSchemes(final Collection<String> targetPreferredAuthSchemes) {
+ this.targetPreferredAuthSchemes = targetPreferredAuthSchemes;
+ return this;
+ }
+
+ public Builder setProxyPreferredAuthSchemes(final Collection<String> proxyPreferredAuthSchemes) {
+ this.proxyPreferredAuthSchemes = proxyPreferredAuthSchemes;
+ return this;
+ }
+
+ public Builder setConnectionRequestTimeout(final int connectionRequestTimeout) {
+ this.connectionRequestTimeout = connectionRequestTimeout;
+ return this;
+ }
+
+ public Builder setConnectTimeout(final int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ return this;
+ }
+
+ public Builder setSocketTimeout(final int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+ return this;
+ }
+
+ public RequestConfig build() {
+ return new RequestConfig(
+ expectContinueEnabled,
+ proxy,
+ localAddress,
+ staleConnectionCheckEnabled,
+ cookieSpec,
+ redirectsEnabled,
+ relativeRedirectsAllowed,
+ circularRedirectsAllowed,
+ maxRedirects,
+ authenticationEnabled,
+ targetPreferredAuthSchemes,
+ proxyPreferredAuthSchemes,
+ connectionRequestTimeout,
+ connectTimeout,
+ socketTimeout);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/package-info.java
new file mode 100644
index 000000000..a7af2d46b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/config/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client configuration APIs.
+ */
+package ch.boye.httpclientandroidlib.client.config;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DecompressingEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DecompressingEntity.java
new file mode 100644
index 000000000..9adec5edb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DecompressingEntity.java
@@ -0,0 +1,105 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Common base class for decompressing {@link HttpEntity} implementations.
+ *
+ * @since 4.1
+ */
+abstract class DecompressingEntity extends HttpEntityWrapper {
+
+ /**
+ * Default buffer size.
+ */
+ private static final int BUFFER_SIZE = 1024 * 2;
+
+ /**
+ * {@link #getContent()} method must return the same {@link InputStream}
+ * instance when DecompressingEntity is wrapping a streaming entity.
+ */
+ private InputStream content;
+
+ /**
+ * Creates a new {@link DecompressingEntity}.
+ *
+ * @param wrapped
+ * the non-null {@link HttpEntity} to be wrapped
+ */
+ public DecompressingEntity(final HttpEntity wrapped) {
+ super(wrapped);
+ }
+
+ abstract InputStream decorate(final InputStream wrapped) throws IOException;
+
+ private InputStream getDecompressingStream() throws IOException {
+ final InputStream in = wrappedEntity.getContent();
+ return new LazyDecompressingInputStream(in, this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public InputStream getContent() throws IOException {
+ if (wrappedEntity.isStreaming()) {
+ if (content == null) {
+ content = getDecompressingStream();
+ }
+ return content;
+ } else {
+ return getDecompressingStream();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ final InputStream instream = getContent();
+ try {
+ final byte[] buffer = new byte[BUFFER_SIZE];
+ int l;
+ while ((l = instream.read(buffer)) != -1) {
+ outstream.write(buffer, 0, l);
+ }
+ } finally {
+ instream.close();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateDecompressingEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateDecompressingEntity.java
new file mode 100644
index 000000000..4bce8b5b5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateDecompressingEntity.java
@@ -0,0 +1,96 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+
+/**
+ * {@link ch.boye.httpclientandroidlib.entity.HttpEntityWrapper} responsible for handling
+ * deflate Content Coded responses. In RFC2616 terms, <code>deflate</code>
+ * means a <code>zlib</code> stream as defined in RFC1950. Some server
+ * implementations have misinterpreted RFC2616 to mean that a
+ * <code>deflate</code> stream as defined in RFC1951 should be used
+ * (or maybe they did that since that's how IE behaves?). It's confusing
+ * that <code>deflate</code> in HTTP 1.1 means <code>zlib</code> streams
+ * rather than <code>deflate</code> streams. We handle both types in here,
+ * since that's what is seen on the internet. Moral - prefer
+ * <code>gzip</code>!
+ *
+ * @see GzipDecompressingEntity
+ *
+ * @since 4.1
+ */
+public class DeflateDecompressingEntity extends DecompressingEntity {
+
+ /**
+ * Creates a new {@link DeflateDecompressingEntity} which will wrap the specified
+ * {@link HttpEntity}.
+ *
+ * @param entity
+ * a non-null {@link HttpEntity} to be wrapped
+ */
+ public DeflateDecompressingEntity(final HttpEntity entity) {
+ super(entity);
+ }
+
+ /**
+ * Returns the non-null InputStream that should be returned to by all requests to
+ * {@link #getContent()}.
+ *
+ * @return a non-null InputStream
+ * @throws IOException if there was a problem
+ */
+ @Override
+ InputStream decorate(final InputStream wrapped) throws IOException {
+ return new DeflateInputStream(wrapped);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Header getContentEncoding() {
+
+ /* This HttpEntityWrapper has dealt with the Content-Encoding. */
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getContentLength() {
+
+ /* Length of inflated content is unknown. */
+ return -1;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateInputStream.java
new file mode 100644
index 000000000..392a28a74
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/DeflateInputStream.java
@@ -0,0 +1,228 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+/** Deflate input stream. This class includes logic needed for various Rfc's in order
+* to reasonably implement the "deflate" compression style.
+*/
+public class DeflateInputStream extends InputStream
+{
+ private InputStream sourceStream;
+
+ public DeflateInputStream(final InputStream wrapped)
+ throws IOException
+ {
+ /*
+ * A zlib stream will have a header.
+ *
+ * CMF | FLG [| DICTID ] | ...compressed data | ADLER32 |
+ *
+ * * CMF is one byte.
+ *
+ * * FLG is one byte.
+ *
+ * * DICTID is four bytes, and only present if FLG.FDICT is set.
+ *
+ * Sniff the content. Does it look like a zlib stream, with a CMF, etc? c.f. RFC1950,
+ * section 2.2. http://tools.ietf.org/html/rfc1950#page-4
+ *
+ * We need to see if it looks like a proper zlib stream, or whether it is just a deflate
+ * stream. RFC2616 calls zlib streams deflate. Confusing, isn't it? That's why some servers
+ * implement deflate Content-Encoding using deflate streams, rather than zlib streams.
+ *
+ * We could start looking at the bytes, but to be honest, someone else has already read
+ * the RFCs and implemented that for us. So we'll just use the JDK libraries and exception
+ * handling to do this. If that proves slow, then we could potentially change this to check
+ * the first byte - does it look like a CMF? What about the second byte - does it look like
+ * a FLG, etc.
+ */
+
+ /* We read a small buffer to sniff the content. */
+ final byte[] peeked = new byte[6];
+
+ final PushbackInputStream pushback = new PushbackInputStream(wrapped, peeked.length);
+
+ final int headerLength = pushback.read(peeked);
+
+ if (headerLength == -1) {
+ throw new IOException("Unable to read the response");
+ }
+
+ /* We try to read the first uncompressed byte. */
+ final byte[] dummy = new byte[1];
+
+ final Inflater inf = new Inflater();
+
+ try {
+ int n;
+ while ((n = inf.inflate(dummy)) == 0) {
+ if (inf.finished()) {
+
+ /* Not expecting this, so fail loudly. */
+ throw new IOException("Unable to read the response");
+ }
+
+ if (inf.needsDictionary()) {
+
+ /* Need dictionary - then it must be zlib stream with DICTID part? */
+ break;
+ }
+
+ if (inf.needsInput()) {
+ inf.setInput(peeked);
+ }
+ }
+
+ if (n == -1) {
+ throw new IOException("Unable to read the response");
+ }
+
+ /*
+ * We read something without a problem, so it's a valid zlib stream. Just need to reset
+ * and return an unused InputStream now.
+ */
+ pushback.unread(peeked, 0, headerLength);
+ sourceStream = new DeflateStream(pushback, new Inflater());
+ } catch (final DataFormatException e) {
+
+ /* Presume that it's an RFC1951 deflate stream rather than RFC1950 zlib stream and try
+ * again. */
+ pushback.unread(peeked, 0, headerLength);
+ sourceStream = new DeflateStream(pushback, new Inflater(true));
+ } finally {
+ inf.end();
+ }
+
+ }
+
+ /** Read a byte.
+ */
+ @Override
+ public int read()
+ throws IOException
+ {
+ return sourceStream.read();
+ }
+
+ /** Read lots of bytes.
+ */
+ @Override
+ public int read(final byte[] b)
+ throws IOException
+ {
+ return sourceStream.read(b);
+ }
+
+ /** Read lots of specific bytes.
+ */
+ @Override
+ public int read(final byte[] b, final int off, final int len)
+ throws IOException
+ {
+ return sourceStream.read(b,off,len);
+ }
+
+ /** Skip
+ */
+ @Override
+ public long skip(final long n)
+ throws IOException
+ {
+ return sourceStream.skip(n);
+ }
+
+ /** Get available.
+ */
+ @Override
+ public int available()
+ throws IOException
+ {
+ return sourceStream.available();
+ }
+
+ /** Mark.
+ */
+ @Override
+ public void mark(final int readLimit)
+ {
+ sourceStream.mark(readLimit);
+ }
+
+ /** Reset.
+ */
+ @Override
+ public void reset()
+ throws IOException
+ {
+ sourceStream.reset();
+ }
+
+ /** Check if mark is supported.
+ */
+ @Override
+ public boolean markSupported()
+ {
+ return sourceStream.markSupported();
+ }
+
+ /** Close.
+ */
+ @Override
+ public void close()
+ throws IOException
+ {
+ sourceStream.close();
+ }
+
+ static class DeflateStream extends InflaterInputStream {
+
+ private boolean closed = false;
+
+ public DeflateStream(final InputStream in, final Inflater inflater) {
+ super(in, inflater);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ inf.end();
+ super.close();
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/EntityBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/EntityBuilder.java
new file mode 100644
index 000000000..ebec48a13
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/EntityBuilder.java
@@ -0,0 +1,342 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.entity;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.entity.AbstractHttpEntity;
+import ch.boye.httpclientandroidlib.entity.BasicHttpEntity;
+import ch.boye.httpclientandroidlib.entity.ByteArrayEntity;
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.FileEntity;
+import ch.boye.httpclientandroidlib.entity.InputStreamEntity;
+import ch.boye.httpclientandroidlib.entity.SerializableEntity;
+import ch.boye.httpclientandroidlib.entity.StringEntity;
+
+/**
+ * Builder for {@link HttpEntity} instances.
+ * <p/>
+ * Several setter methods of this builder are mutually exclusive. In case of multiple invocations
+ * of the following methods only the last one will have effect:
+ * <ul>
+ * <li>{@link #setText(String)}</li>
+ * <li>{@link #setBinary(byte[])}</li>
+ * <li>{@link #setStream(java.io.InputStream)}</li>
+ * <li>{@link #setSerializable(java.io.Serializable)}</li>
+ * <li>{@link #setParameters(java.util.List)}</li>
+ * <li>{@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}</li>
+ * <li>{@link #setFile(java.io.File)}</li>
+ * </ul>
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class EntityBuilder {
+
+ private String text;
+ private byte[] binary;
+ private InputStream stream;
+ private List<NameValuePair> parameters;
+ private Serializable serializable;
+ private File file;
+ private ContentType contentType;
+ private String contentEncoding;
+ private boolean chunked;
+ private boolean gzipCompress;
+
+ EntityBuilder() {
+ super();
+ }
+
+ public static EntityBuilder create() {
+ return new EntityBuilder();
+ }
+
+ private void clearContent() {
+ this.text = null;
+ this.binary = null;
+ this.stream = null;
+ this.parameters = null;
+ this.serializable = null;
+ this.file = null;
+ }
+
+ /**
+ * Returns entity content as a string if set using {@link #setText(String)} method.
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets entity content as a string. This method is mutually exclusive with
+ * {@link #setBinary(byte[])},
+ * {@link #setStream(java.io.InputStream)} ,
+ * {@link #setSerializable(java.io.Serializable)} ,
+ * {@link #setParameters(java.util.List)},
+ * {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
+ * {@link #setFile(java.io.File)} methods.
+ */
+ public EntityBuilder setText(final String text) {
+ clearContent();
+ this.text = text;
+ return this;
+ }
+
+ /**
+ * Returns entity content as a byte array if set using
+ * {@link #setBinary(byte[])} method.
+ */
+ public byte[] getBinary() {
+ return binary;
+ }
+
+ /**
+ * Sets entity content as a byte array. This method is mutually exclusive with
+ * {@link #setText(String)},
+ * {@link #setStream(java.io.InputStream)} ,
+ * {@link #setSerializable(java.io.Serializable)} ,
+ * {@link #setParameters(java.util.List)},
+ * {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
+ * {@link #setFile(java.io.File)} methods.
+ */
+ public EntityBuilder setBinary(final byte[] binary) {
+ clearContent();
+ this.binary = binary;
+ return this;
+ }
+
+ /**
+ * Returns entity content as a {@link InputStream} if set using
+ * {@link #setStream(java.io.InputStream)} method.
+ */
+ public InputStream getStream() {
+ return stream;
+ }
+
+ /**
+ * Sets entity content as a {@link InputStream}. This method is mutually exclusive with
+ * {@link #setText(String)},
+ * {@link #setBinary(byte[])},
+ * {@link #setSerializable(java.io.Serializable)} ,
+ * {@link #setParameters(java.util.List)},
+ * {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
+ * {@link #setFile(java.io.File)} methods.
+ */
+ public EntityBuilder setStream(final InputStream stream) {
+ clearContent();
+ this.stream = stream;
+ return this;
+ }
+
+ /**
+ * Returns entity content as a parameter list if set using
+ * {@link #setParameters(java.util.List)} or
+ * {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)} methods.
+ */
+ public List<NameValuePair> getParameters() {
+ return parameters;
+ }
+
+ /**
+ * Sets entity content as a parameter list. This method is mutually exclusive with
+ * {@link #setText(String)},
+ * {@link #setBinary(byte[])},
+ * {@link #setStream(java.io.InputStream)} ,
+ * {@link #setSerializable(java.io.Serializable)} ,
+ * {@link #setFile(java.io.File)} methods.
+ */
+ public EntityBuilder setParameters(final List<NameValuePair> parameters) {
+ clearContent();
+ this.parameters = parameters;
+ return this;
+ }
+
+ /**
+ * Sets entity content as a parameter list. This method is mutually exclusive with
+ * {@link #setText(String)},
+ * {@link #setBinary(byte[])},
+ * {@link #setStream(java.io.InputStream)} ,
+ * {@link #setSerializable(java.io.Serializable)} ,
+ * {@link #setFile(java.io.File)} methods.
+ */
+ public EntityBuilder setParameters(final NameValuePair... parameters) {
+ return setParameters(Arrays.asList(parameters));
+ }
+
+ /**
+ * Returns entity content as a {@link Serializable} if set using
+ * {@link #setSerializable(java.io.Serializable)} method.
+ */
+ public Serializable getSerializable() {
+ return serializable;
+ }
+
+ /**
+ * Sets entity content as a {@link Serializable}. This method is mutually exclusive with
+ * {@link #setText(String)},
+ * {@link #setBinary(byte[])},
+ * {@link #setStream(java.io.InputStream)} ,
+ * {@link #setParameters(java.util.List)},
+ * {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
+ * {@link #setFile(java.io.File)} methods.
+ */
+ public EntityBuilder setSerializable(final Serializable serializable) {
+ clearContent();
+ this.serializable = serializable;
+ return this;
+ }
+
+ /**
+ * Returns entity content as a {@link File} if set using
+ * {@link #setFile(java.io.File)} method.
+ */
+ public File getFile() {
+ return file;
+ }
+
+ /**
+ * Sets entity content as a {@link File}. This method is mutually exclusive with
+ * {@link #setText(String)},
+ * {@link #setBinary(byte[])},
+ * {@link #setStream(java.io.InputStream)} ,
+ * {@link #setParameters(java.util.List)},
+ * {@link #setParameters(ch.boye.httpclientandroidlib.NameValuePair...)}
+ * {@link #setSerializable(java.io.Serializable)} methods.
+ */
+ public EntityBuilder setFile(final File file) {
+ clearContent();
+ this.file = file;
+ return this;
+ }
+
+ /**
+ * Returns {@link ContentType} of the entity, if set.
+ */
+ public ContentType getContentType() {
+ return contentType;
+ }
+
+ /**
+ * Sets {@link ContentType} of the entity.
+ */
+ public EntityBuilder setContentType(final ContentType contentType) {
+ this.contentType = contentType;
+ return this;
+ }
+
+ /**
+ * Returns content encoding of the entity, if set.
+ */
+ public String getContentEncoding() {
+ return contentEncoding;
+ }
+
+ /**
+ * Sets content encoding of the entity.
+ */
+ public EntityBuilder setContentEncoding(final String contentEncoding) {
+ this.contentEncoding = contentEncoding;
+ return this;
+ }
+
+ /**
+ * Returns <code>true</code> if entity is to be chunk coded, <code>false</code> otherwise.
+ */
+ public boolean isChunked() {
+ return chunked;
+ }
+
+ /**
+ * Makes entity chunk coded.
+ */
+ public EntityBuilder chunked() {
+ this.chunked = true;
+ return this;
+ }
+
+ /**
+ * Returns <code>true</code> if entity is to be GZIP compressed, <code>false</code> otherwise.
+ */
+ public boolean isGzipCompress() {
+ return gzipCompress;
+ }
+
+ /**
+ * Makes entity GZIP compressed.
+ */
+ public EntityBuilder gzipCompress() {
+ this.gzipCompress = true;
+ return this;
+ }
+
+ private ContentType getContentOrDefault(final ContentType def) {
+ return this.contentType != null ? this.contentType : def;
+ }
+
+ /**
+ * Creates new instance of {@link HttpEntity} based on the current state.
+ */
+ public HttpEntity build() {
+ final AbstractHttpEntity e;
+ if (this.text != null) {
+ e = new StringEntity(this.text, getContentOrDefault(ContentType.DEFAULT_TEXT));
+ } else if (this.binary != null) {
+ e = new ByteArrayEntity(this.binary, getContentOrDefault(ContentType.DEFAULT_BINARY));
+ } else if (this.stream != null) {
+ e = new InputStreamEntity(this.stream, 1, getContentOrDefault(ContentType.DEFAULT_BINARY));
+ } else if (this.parameters != null) {
+ e = new UrlEncodedFormEntity(this.parameters,
+ this.contentType != null ? this.contentType.getCharset() : null);
+ } else if (this.serializable != null) {
+ e = new SerializableEntity(this.serializable);
+ e.setContentType(ContentType.DEFAULT_BINARY.toString());
+ } else if (this.file != null) {
+ e = new FileEntity(this.file, getContentOrDefault(ContentType.DEFAULT_BINARY));
+ } else {
+ e = new BasicHttpEntity();
+ }
+ if (e.getContentType() != null && this.contentType != null) {
+ e.setContentType(this.contentType.toString());
+ }
+ e.setContentEncoding(this.contentEncoding);
+ e.setChunked(this.chunked);
+ if (this.gzipCompress) {
+ return new GzipCompressingEntity(e);
+ }
+ return e;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipCompressingEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipCompressingEntity.java
new file mode 100644
index 000000000..89925a2b9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipCompressingEntity.java
@@ -0,0 +1,113 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.entity;
+
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.GZIPOutputStream;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Wrapping entity that compresses content when {@link #writeTo writing}.
+ *
+ *
+ * @since 4.0
+ */
+public class GzipCompressingEntity extends HttpEntityWrapper {
+
+ private static final String GZIP_CODEC = "gzip";
+
+ public GzipCompressingEntity(final HttpEntity entity) {
+ super(entity);
+ }
+
+ @Override
+ public Header getContentEncoding() {
+ return new BasicHeader(HTTP.CONTENT_ENCODING, GZIP_CODEC);
+ }
+
+ @Override
+ public long getContentLength() {
+ return -1;
+ }
+
+ @Override
+ public boolean isChunked() {
+ // force content chunking
+ return true;
+ }
+
+ @Override
+ public InputStream getContent() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ final GZIPOutputStream gzip = new GZIPOutputStream(outstream);
+ wrappedEntity.writeTo(gzip);
+ // Only close output stream if the wrapped entity has been
+ // successfully written out
+ gzip.close();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipDecompressingEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipDecompressingEntity.java
new file mode 100644
index 000000000..a3dd5b259
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/GzipDecompressingEntity.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+
+/**
+ * {@link ch.boye.httpclientandroidlib.entity.HttpEntityWrapper} for handling gzip
+ * Content Coded responses.
+ *
+ * @since 4.1
+ */
+public class GzipDecompressingEntity extends DecompressingEntity {
+
+ /**
+ * Creates a new {@link GzipDecompressingEntity} which will wrap the specified
+ * {@link HttpEntity}.
+ *
+ * @param entity
+ * the non-null {@link HttpEntity} to be wrapped
+ */
+ public GzipDecompressingEntity(final HttpEntity entity) {
+ super(entity);
+ }
+
+ @Override
+ InputStream decorate(final InputStream wrapped) throws IOException {
+ return new GZIPInputStream(wrapped);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Header getContentEncoding() {
+
+ /* This HttpEntityWrapper has dealt with the Content-Encoding. */
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getContentLength() {
+
+ /* length of ungzipped content is not known */
+ return -1;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/LazyDecompressingInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/LazyDecompressingInputStream.java
new file mode 100644
index 000000000..60215ff15
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/LazyDecompressingInputStream.java
@@ -0,0 +1,105 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.entity;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Lazy init InputStream wrapper.
+ */
+@NotThreadSafe
+class LazyDecompressingInputStream extends InputStream {
+
+ private final InputStream wrappedStream;
+
+ private final DecompressingEntity decompressingEntity;
+
+ private InputStream wrapperStream;
+
+ public LazyDecompressingInputStream(
+ final InputStream wrappedStream,
+ final DecompressingEntity decompressingEntity) {
+ this.wrappedStream = wrappedStream;
+ this.decompressingEntity = decompressingEntity;
+ }
+
+ private void initWrapper() throws IOException {
+ if (wrapperStream == null) {
+ wrapperStream = decompressingEntity.decorate(wrappedStream);
+ }
+ }
+
+ @Override
+ public int read() throws IOException {
+ initWrapper();
+ return wrapperStream.read();
+ }
+
+ @Override
+ public int read(final byte[] b) throws IOException {
+ initWrapper();
+ return wrapperStream.read(b);
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ initWrapper();
+ return wrapperStream.read(b, off, len);
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ initWrapper();
+ return wrapperStream.skip(n);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ @Override
+ public int available() throws IOException {
+ initWrapper();
+ return wrapperStream.available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ if (wrapperStream != null) {
+ wrapperStream.close();
+ }
+ } finally {
+ wrappedStream.close();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/UrlEncodedFormEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/UrlEncodedFormEntity.java
new file mode 100644
index 000000000..855155927
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/UrlEncodedFormEntity.java
@@ -0,0 +1,107 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.entity;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils;
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.StringEntity;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * An entity composed of a list of url-encoded pairs.
+ * This is typically useful while sending an HTTP POST request.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // AbstractHttpEntity is not thread-safe
+public class UrlEncodedFormEntity extends StringEntity {
+
+ /**
+ * Constructs a new {@link UrlEncodedFormEntity} with the list
+ * of parameters in the specified encoding.
+ *
+ * @param parameters list of name/value pairs
+ * @param charset encoding the name/value pairs be encoded with
+ * @throws UnsupportedEncodingException if the encoding isn't supported
+ */
+ public UrlEncodedFormEntity (
+ final List <? extends NameValuePair> parameters,
+ final String charset) throws UnsupportedEncodingException {
+ super(URLEncodedUtils.format(parameters,
+ charset != null ? charset : HTTP.DEF_CONTENT_CHARSET.name()),
+ ContentType.create(URLEncodedUtils.CONTENT_TYPE, charset));
+ }
+
+ /**
+ * Constructs a new {@link UrlEncodedFormEntity} with the list
+ * of parameters in the specified encoding.
+ *
+ * @param parameters iterable collection of name/value pairs
+ * @param charset encoding the name/value pairs be encoded with
+ *
+ * @since 4.2
+ */
+ public UrlEncodedFormEntity (
+ final Iterable <? extends NameValuePair> parameters,
+ final Charset charset) {
+ super(URLEncodedUtils.format(parameters,
+ charset != null ? charset : HTTP.DEF_CONTENT_CHARSET),
+ ContentType.create(URLEncodedUtils.CONTENT_TYPE, charset));
+ }
+
+ /**
+ * Constructs a new {@link UrlEncodedFormEntity} with the list
+ * of parameters with the default encoding of {@link HTTP#DEFAULT_CONTENT_CHARSET}
+ *
+ * @param parameters list of name/value pairs
+ * @throws UnsupportedEncodingException if the default encoding isn't supported
+ */
+ public UrlEncodedFormEntity (
+ final List <? extends NameValuePair> parameters) throws UnsupportedEncodingException {
+ this(parameters, (Charset) null);
+ }
+
+ /**
+ * Constructs a new {@link UrlEncodedFormEntity} with the list
+ * of parameters with the default encoding of {@link HTTP#DEFAULT_CONTENT_CHARSET}
+ *
+ * @param parameters iterable collection of name/value pairs
+ *
+ * @since 4.2
+ */
+ public UrlEncodedFormEntity (
+ final Iterable <? extends NameValuePair> parameters) {
+ this(parameters, null);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/package-info.java
new file mode 100644
index 000000000..703f80d58
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/entity/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client specific HTTP entity implementations.
+ */
+package ch.boye.httpclientandroidlib.client.entity;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbortableHttpRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbortableHttpRequest.java
new file mode 100644
index 000000000..92715c26a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbortableHttpRequest.java
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.ConnectionReleaseTrigger;
+
+import java.io.IOException;
+
+
+/**
+ * Interface representing an HTTP request that can be aborted by shutting
+ * down the underlying HTTP connection.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link HttpExecutionAware}
+ */
+@Deprecated
+public interface AbortableHttpRequest {
+
+ /**
+ * Sets the {@link ch.boye.httpclientandroidlib.conn.ClientConnectionRequest}
+ * callback that can be used to abort a long-lived request for a connection.
+ * If the request is already aborted, throws an {@link IOException}.
+ *
+ * @see ch.boye.httpclientandroidlib.conn.ClientConnectionManager
+ */
+ void setConnectionRequest(ClientConnectionRequest connRequest) throws IOException;
+
+ /**
+ * Sets the {@link ConnectionReleaseTrigger} callback that can
+ * be used to abort an active connection.
+ * Typically, this will be the
+ * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} itself.
+ * If the request is already aborted, throws an {@link IOException}.
+ */
+ void setReleaseTrigger(ConnectionReleaseTrigger releaseTrigger) throws IOException;
+
+ /**
+ * Aborts this http request. Any active execution of this method should
+ * return immediately. If the request has not started, it will abort after
+ * the next execution. Aborting this request will cause all subsequent
+ * executions with this request to fail.
+ *
+ * @see ch.boye.httpclientandroidlib.client.HttpClient#execute(HttpUriRequest)
+ * @see ch.boye.httpclientandroidlib.client.HttpClient#execute(ch.boye.httpclientandroidlib.HttpHost,
+ * ch.boye.httpclientandroidlib.HttpRequest)
+ * @see ch.boye.httpclientandroidlib.client.HttpClient#execute(HttpUriRequest,
+ * ch.boye.httpclientandroidlib.protocol.HttpContext)
+ * @see ch.boye.httpclientandroidlib.client.HttpClient#execute(ch.boye.httpclientandroidlib.HttpHost,
+ * ch.boye.httpclientandroidlib.HttpRequest, ch.boye.httpclientandroidlib.protocol.HttpContext)
+ */
+ void abort();
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbstractExecutionAwareRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbstractExecutionAwareRequest.java
new file mode 100644
index 000000000..2525769c3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/AbstractExecutionAwareRequest.java
@@ -0,0 +1,131 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.client.utils.CloneUtils;
+import ch.boye.httpclientandroidlib.concurrent.Cancellable;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.ConnectionReleaseTrigger;
+import ch.boye.httpclientandroidlib.message.AbstractHttpMessage;
+
+@SuppressWarnings("deprecation")
+public abstract class AbstractExecutionAwareRequest extends AbstractHttpMessage implements
+ HttpExecutionAware, AbortableHttpRequest, Cloneable, HttpRequest {
+
+ private final AtomicBoolean aborted;
+ private final AtomicReference<Cancellable> cancellableRef;
+
+ protected AbstractExecutionAwareRequest() {
+ super();
+ this.aborted = new AtomicBoolean(false);
+ this.cancellableRef = new AtomicReference<Cancellable>(null);
+ }
+
+ @Deprecated
+ public void setConnectionRequest(final ClientConnectionRequest connRequest) {
+ setCancellable(new Cancellable() {
+
+ public boolean cancel() {
+ connRequest.abortRequest();
+ return true;
+ }
+
+ });
+ }
+
+ @Deprecated
+ public void setReleaseTrigger(final ConnectionReleaseTrigger releaseTrigger) {
+ setCancellable(new Cancellable() {
+
+ public boolean cancel() {
+ try {
+ releaseTrigger.abortConnection();
+ return true;
+ } catch (final IOException ex) {
+ return false;
+ }
+ }
+
+ });
+ }
+
+ public void abort() {
+ if (this.aborted.compareAndSet(false, true)) {
+ final Cancellable cancellable = this.cancellableRef.getAndSet(null);
+ if (cancellable != null) {
+ cancellable.cancel();
+ }
+ }
+ }
+
+ public boolean isAborted() {
+ return this.aborted.get();
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void setCancellable(final Cancellable cancellable) {
+ if (!this.aborted.get()) {
+ this.cancellableRef.set(cancellable);
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ final AbstractExecutionAwareRequest clone = (AbstractExecutionAwareRequest) super.clone();
+ clone.headergroup = CloneUtils.cloneObject(this.headergroup);
+ clone.params = CloneUtils.cloneObject(this.params);
+ return clone;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void completed() {
+ this.cancellableRef.set(null);
+ }
+
+ /**
+ * Resets internal state of the request making it reusable.
+ *
+ * @since 4.2
+ */
+ public void reset() {
+ final Cancellable cancellable = this.cancellableRef.getAndSet(null);
+ if (cancellable != null) {
+ cancellable.cancel();
+ }
+ this.aborted.set(false);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/CloseableHttpResponse.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/CloseableHttpResponse.java
new file mode 100644
index 000000000..471a11219
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/CloseableHttpResponse.java
@@ -0,0 +1,40 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.io.Closeable;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+/**
+ * Extended version of the {@link HttpResponse} interface that also extends {@link Closeable}.
+ *
+ * @since 4.3
+ */
+public interface CloseableHttpResponse extends HttpResponse, Closeable {
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/Configurable.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/Configurable.java
new file mode 100644
index 000000000..74f014f20
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/Configurable.java
@@ -0,0 +1,44 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+
+/**
+ * Configuration interface for HTTP requests.
+ *
+ * @since 4.3
+ */
+public interface Configurable {
+
+ /**
+ * Returns actual request configuration.
+ */
+ RequestConfig getConfig();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpDelete.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpDelete.java
new file mode 100644
index 000000000..20baf651c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpDelete.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * HTTP DELETE method
+ * <p>
+ * The HTTP DELETE method is defined in section 9.7 of
+ * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
+ * <blockquote>
+ * The DELETE method requests that the origin server delete the resource
+ * identified by the Request-URI. [...] The client cannot
+ * be guaranteed that the operation has been carried out, even if the
+ * status code returned from the origin server indicates that the action
+ * has been completed successfully.
+ * </blockquote>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // HttpRequestBase is @NotThreadSafe
+public class HttpDelete extends HttpRequestBase {
+
+ public final static String METHOD_NAME = "DELETE";
+
+
+ public HttpDelete() {
+ super();
+ }
+
+ public HttpDelete(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the uri is invalid.
+ */
+ public HttpDelete(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java
new file mode 100644
index 000000000..cbc035ade
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java
@@ -0,0 +1,76 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.utils.CloneUtils;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * Basic implementation of an entity enclosing HTTP request
+ * that can be modified
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // HttpRequestBase is @NotThreadSafe
+public abstract class HttpEntityEnclosingRequestBase
+ extends HttpRequestBase implements HttpEntityEnclosingRequest {
+
+ private HttpEntity entity;
+
+ public HttpEntityEnclosingRequestBase() {
+ super();
+ }
+
+ public HttpEntity getEntity() {
+ return this.entity;
+ }
+
+ public void setEntity(final HttpEntity entity) {
+ this.entity = entity;
+ }
+
+ public boolean expectContinue() {
+ final Header expect = getFirstHeader(HTTP.EXPECT_DIRECTIVE);
+ return expect != null && HTTP.EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue());
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ final HttpEntityEnclosingRequestBase clone =
+ (HttpEntityEnclosingRequestBase) super.clone();
+ if (this.entity != null) {
+ clone.entity = CloneUtils.cloneObject(this.entity);
+ }
+ return clone;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpExecutionAware.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpExecutionAware.java
new file mode 100644
index 000000000..6dab381d3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpExecutionAware.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import ch.boye.httpclientandroidlib.concurrent.Cancellable;
+
+/**
+ * Interface to be implemented by any object that wishes to be notified of
+ * blocking I/O operations that could be cancelled.
+ *
+ * @since 4.3
+ */
+public interface HttpExecutionAware {
+
+ boolean isAborted();
+
+ /**
+ * Sets {@link Cancellable} for the ongoing operation.
+ */
+ void setCancellable(Cancellable cancellable);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpGet.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpGet.java
new file mode 100644
index 000000000..33de1a8dc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpGet.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * HTTP GET method.
+ * <p>
+ * The HTTP GET method is defined in section 9.3 of
+ * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
+ * <blockquote>
+ * The GET method means retrieve whatever information (in the form of an
+ * entity) is identified by the Request-URI. If the Request-URI refers
+ * to a data-producing process, it is the produced data which shall be
+ * returned as the entity in the response and not the source text of the
+ * process, unless that text happens to be the output of the process.
+ * </blockquote>
+ * </p>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpGet extends HttpRequestBase {
+
+ public final static String METHOD_NAME = "GET";
+
+ public HttpGet() {
+ super();
+ }
+
+ public HttpGet(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the uri is invalid.
+ */
+ public HttpGet(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpHead.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpHead.java
new file mode 100644
index 000000000..58ab5b00b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpHead.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * HTTP HEAD method.
+ * <p>
+ * The HTTP HEAD method is defined in section 9.4 of
+ * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
+ * <blockquote>
+ * The HEAD method is identical to GET except that the server MUST NOT
+ * return a message-body in the response. The metainformation contained
+ * in the HTTP headers in response to a HEAD request SHOULD be identical
+ * to the information sent in response to a GET request. This method can
+ * be used for obtaining metainformation about the entity implied by the
+ * request without transferring the entity-body itself. This method is
+ * often used for testing hypertext links for validity, accessibility,
+ * and recent modification.
+ * </blockquote>
+ * </p>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpHead extends HttpRequestBase {
+
+ public final static String METHOD_NAME = "HEAD";
+
+ public HttpHead() {
+ super();
+ }
+
+ public HttpHead(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the uri is invalid.
+ */
+ public HttpHead(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpOptions.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpOptions.java
new file mode 100644
index 000000000..af3ee251b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpOptions.java
@@ -0,0 +1,100 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * HTTP OPTIONS method.
+ * <p>
+ * The HTTP OPTIONS method is defined in section 9.2 of
+ * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
+ * <blockquote>
+ * The OPTIONS method represents a request for information about the
+ * communication options available on the request/response chain
+ * identified by the Request-URI. This method allows the client to
+ * determine the options and/or requirements associated with a resource,
+ * or the capabilities of a server, without implying a resource action
+ * or initiating a resource retrieval.
+ * </blockquote>
+ * </p>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpOptions extends HttpRequestBase {
+
+ public final static String METHOD_NAME = "OPTIONS";
+
+ public HttpOptions() {
+ super();
+ }
+
+ public HttpOptions(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the uri is invalid.
+ */
+ public HttpOptions(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+ public Set<String> getAllowedMethods(final HttpResponse response) {
+ Args.notNull(response, "HTTP response");
+
+ final HeaderIterator it = response.headerIterator("Allow");
+ final Set<String> methods = new HashSet<String>();
+ while (it.hasNext()) {
+ final Header header = it.nextHeader();
+ final HeaderElement[] elements = header.getElements();
+ for (final HeaderElement element : elements) {
+ methods.add(element.getName());
+ }
+ }
+ return methods;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPatch.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPatch.java
new file mode 100644
index 000000000..8cfd29fbb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPatch.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * HTTP PATCH method.
+ * <p>
+ * The HTTP PATCH method is defined in <a
+ * href="http://tools.ietf.org/html/rfc5789">RF5789</a>: <blockquote> The PATCH
+ * method requests that a set of changes described in the request entity be
+ * applied to the resource identified by the Request- URI. Differs from the PUT
+ * method in the way the server processes the enclosed entity to modify the
+ * resource identified by the Request-URI. In a PUT request, the enclosed entity
+ * origin server, and the client is requesting that the stored version be
+ * replaced. With PATCH, however, the enclosed entity contains a set of
+ * instructions describing how a resource currently residing on the origin
+ * server should be modified to produce a new version. </blockquote>
+ * </p>
+ *
+ * @since 4.2
+ */
+@NotThreadSafe
+public class HttpPatch extends HttpEntityEnclosingRequestBase {
+
+ public final static String METHOD_NAME = "PATCH";
+
+ public HttpPatch() {
+ super();
+ }
+
+ public HttpPatch(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ public HttpPatch(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPost.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPost.java
new file mode 100644
index 000000000..f70538b80
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPost.java
@@ -0,0 +1,84 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * HTTP POST method.
+ * <p>
+ * The HTTP POST method is defined in section 9.5 of
+ * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
+ * <blockquote>
+ * The POST method is used to request that the origin server accept the entity
+ * enclosed in the request as a new subordinate of the resource identified by
+ * the Request-URI in the Request-Line. POST is designed to allow a uniform
+ * method to cover the following functions:
+ * <ul>
+ * <li>Annotation of existing resources</li>
+ * <li>Posting a message to a bulletin board, newsgroup, mailing list, or
+ * similar group of articles</li>
+ * <li>Providing a block of data, such as the result of submitting a form,
+ * to a data-handling process</li>
+ * <li>Extending a database through an append operation</li>
+ * </ul>
+ * </blockquote>
+ * </p>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpPost extends HttpEntityEnclosingRequestBase {
+
+ public final static String METHOD_NAME = "POST";
+
+ public HttpPost() {
+ super();
+ }
+
+ public HttpPost(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the uri is invalid.
+ */
+ public HttpPost(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPut.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPut.java
new file mode 100644
index 000000000..4aab04b23
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpPut.java
@@ -0,0 +1,76 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * HTTP PUT method.
+ * <p>
+ * The HTTP PUT method is defined in section 9.6 of
+ * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
+ * <blockquote>
+ * The PUT method requests that the enclosed entity be stored under the
+ * supplied Request-URI. If the Request-URI refers to an already
+ * existing resource, the enclosed entity SHOULD be considered as a
+ * modified version of the one residing on the origin server.
+ * </blockquote>
+ * </p>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpPut extends HttpEntityEnclosingRequestBase {
+
+ public final static String METHOD_NAME = "PUT";
+
+ public HttpPut() {
+ super();
+ }
+
+ public HttpPut(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the uri is invalid.
+ */
+ public HttpPut(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestBase.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestBase.java
new file mode 100644
index 000000000..da3b01ef5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestBase.java
@@ -0,0 +1,124 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.message.BasicRequestLine;
+import ch.boye.httpclientandroidlib.params.HttpProtocolParams;
+
+/**
+ * Base implementation of {@link HttpUriRequest}.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public abstract class HttpRequestBase extends AbstractExecutionAwareRequest
+ implements HttpUriRequest, Configurable {
+
+ private ProtocolVersion version;
+ private URI uri;
+ private RequestConfig config;
+
+ public abstract String getMethod();
+
+ /**
+ * @since 4.3
+ */
+ public void setProtocolVersion(final ProtocolVersion version) {
+ this.version = version;
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ return version != null ? version : HttpProtocolParams.getVersion(getParams());
+ }
+
+ /**
+ * Returns the original request URI.
+ * <p>
+ * Please note URI remains unchanged in the course of request execution and
+ * is not updated if the request is redirected to another location.
+ */
+ public URI getURI() {
+ return this.uri;
+ }
+
+ public RequestLine getRequestLine() {
+ final String method = getMethod();
+ final ProtocolVersion ver = getProtocolVersion();
+ final URI uri = getURI();
+ String uritext = null;
+ if (uri != null) {
+ uritext = uri.toASCIIString();
+ }
+ if (uritext == null || uritext.length() == 0) {
+ uritext = "/";
+ }
+ return new BasicRequestLine(method, uritext, ver);
+ }
+
+
+ public RequestConfig getConfig() {
+ return config;
+ }
+
+ public void setConfig(final RequestConfig config) {
+ this.config = config;
+ }
+
+ public void setURI(final URI uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void started() {
+ }
+
+ /**
+ * A convenience method to simplify migration from HttpClient 3.1 API. This method is
+ * equivalent to {@link #reset()}.
+ *
+ * @since 4.2
+ */
+ public void releaseConnection() {
+ reset();
+ }
+
+ @Override
+ public String toString() {
+ return getMethod() + " " + getURI() + " " + getProtocolVersion();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestWrapper.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestWrapper.java
new file mode 100644
index 000000000..72b7e2c55
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpRequestWrapper.java
@@ -0,0 +1,171 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.message.AbstractHttpMessage;
+import ch.boye.httpclientandroidlib.message.BasicRequestLine;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * A wrapper class for {@link HttpRequest} that can be used to change properties of the current
+ * request without modifying the original object.
+ *
+ * @since 4.3
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public class HttpRequestWrapper extends AbstractHttpMessage implements HttpUriRequest {
+
+ private final HttpRequest original;
+ private final String method;
+ private ProtocolVersion version;
+ private URI uri;
+
+ private HttpRequestWrapper(final HttpRequest request) {
+ super();
+ this.original = request;
+ this.version = this.original.getRequestLine().getProtocolVersion();
+ this.method = this.original.getRequestLine().getMethod();
+ if (request instanceof HttpUriRequest) {
+ this.uri = ((HttpUriRequest) request).getURI();
+ } else {
+ this.uri = null;
+ }
+ setHeaders(request.getAllHeaders());
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ return this.version != null ? this.version : this.original.getProtocolVersion();
+ }
+
+ public void setProtocolVersion(final ProtocolVersion version) {
+ this.version = version;
+ }
+
+ public URI getURI() {
+ return this.uri;
+ }
+
+ public void setURI(final URI uri) {
+ this.uri = uri;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void abort() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isAborted() {
+ return false;
+ }
+
+ public RequestLine getRequestLine() {
+ String requestUri = null;
+ if (this.uri != null) {
+ requestUri = this.uri.toASCIIString();
+ } else {
+ requestUri = this.original.getRequestLine().getUri();
+ }
+ if (requestUri == null || requestUri.length() == 0) {
+ requestUri = "/";
+ }
+ return new BasicRequestLine(this.method, requestUri, getProtocolVersion());
+ }
+
+ public HttpRequest getOriginal() {
+ return this.original;
+ }
+
+ @Override
+ public String toString() {
+ return getRequestLine() + " " + this.headergroup;
+ }
+
+ static class HttpEntityEnclosingRequestWrapper extends HttpRequestWrapper
+ implements HttpEntityEnclosingRequest {
+
+ private HttpEntity entity;
+
+ public HttpEntityEnclosingRequestWrapper(final HttpEntityEnclosingRequest request) {
+ super(request);
+ this.entity = request.getEntity();
+ }
+
+ public HttpEntity getEntity() {
+ return this.entity;
+ }
+
+ public void setEntity(final HttpEntity entity) {
+ this.entity = entity;
+ }
+
+ public boolean expectContinue() {
+ final Header expect = getFirstHeader(HTTP.EXPECT_DIRECTIVE);
+ return expect != null && HTTP.EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue());
+ }
+
+ }
+
+ public static HttpRequestWrapper wrap(final HttpRequest request) {
+ if (request == null) {
+ return null;
+ }
+ if (request instanceof HttpEntityEnclosingRequest) {
+ return new HttpEntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request);
+ } else {
+ return new HttpRequestWrapper(request);
+ }
+ }
+
+ /**
+ * @deprecated (4.3) use
+ * {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
+ */
+ @Override
+ @Deprecated
+ public HttpParams getParams() {
+ if (this.params == null) {
+ this.params = original.getParams().copy();
+ }
+ return this.params;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpTrace.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpTrace.java
new file mode 100644
index 000000000..1118ea181
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpTrace.java
@@ -0,0 +1,79 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * HTTP TRACE method.
+ * <p>
+ * The HTTP TRACE method is defined in section 9.6 of
+ * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
+ * <blockquote>
+ * The TRACE method is used to invoke a remote, application-layer loop-
+ * back of the request message. The final recipient of the request
+ * SHOULD reflect the message received back to the client as the
+ * entity-body of a 200 (OK) response. The final recipient is either the
+ * origin server or the first proxy or gateway to receive a Max-Forwards
+ * value of zero (0) in the request (see section 14.31). A TRACE request
+ * MUST NOT include an entity.
+ * </blockquote>
+ * </p>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpTrace extends HttpRequestBase {
+
+ public final static String METHOD_NAME = "TRACE";
+
+ public HttpTrace() {
+ super();
+ }
+
+ public HttpTrace(final URI uri) {
+ super();
+ setURI(uri);
+ }
+
+ /**
+ * @throws IllegalArgumentException if the uri is invalid.
+ */
+ public HttpTrace(final String uri) {
+ super();
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpUriRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpUriRequest.java
new file mode 100644
index 000000000..8ab14ef85
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/HttpUriRequest.java
@@ -0,0 +1,84 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+
+/**
+ * Extended version of the {@link HttpRequest} interface that provides
+ * convenience methods to access request properties such as request URI
+ * and method type.
+ *
+ * @since 4.0
+ */
+public interface HttpUriRequest extends HttpRequest {
+
+ /**
+ * Returns the HTTP method this request uses, such as <code>GET</code>,
+ * <code>PUT</code>, <code>POST</code>, or other.
+ */
+ String getMethod();
+
+ /**
+ * Returns the URI this request uses, such as
+ * <code>http://example.org/path/to/file</code>.
+ * <br/>
+ * Note that the URI may be absolute URI (as above) or may be a relative URI.
+ * <p>
+ * Implementations are encouraged to return
+ * the URI that was initially requested.
+ * </p>
+ * <p>
+ * To find the final URI after any redirects have been processed,
+ * please see the section entitled
+ * <a href="http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d4e205">HTTP execution context</a>
+ * in the
+ * <a href="http://hc.apache.org/httpcomponents-client-ga/tutorial/html">HttpClient Tutorial</a>
+ * </p>
+ */
+ URI getURI();
+
+ /**
+ * Aborts execution of the request.
+ *
+ * @throws UnsupportedOperationException if the abort operation
+ * is not supported / cannot be implemented.
+ */
+ void abort() throws UnsupportedOperationException;
+
+ /**
+ * Tests if the request execution has been aborted.
+ *
+ * @return <code>true</code> if the request execution has been aborted,
+ * <code>false</code> otherwise.
+ */
+ boolean isAborted();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/RequestBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/RequestBuilder.java
new file mode 100644
index 000000000..3a45dcd2f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/RequestBuilder.java
@@ -0,0 +1,351 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.methods;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
+import ch.boye.httpclientandroidlib.client.utils.URIBuilder;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
+import ch.boye.httpclientandroidlib.message.HeaderGroup;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Builder for {@link HttpUriRequest} instances.
+ * <p/>
+ * Please note that this class treats parameters differently depending on composition
+ * of the request: if the request has a content entity explicitly set with
+ * {@link #setEntity(ch.boye.httpclientandroidlib.HttpEntity)} or it is not an entity enclosing method
+ * (such as POST or PUT), parameters will be added to the query component of the request URI.
+ * Otherwise, parameters will be added as a URL encoded {@link UrlEncodedFormEntity entity}.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class RequestBuilder {
+
+ private String method;
+ private ProtocolVersion version;
+ private URI uri;
+ private HeaderGroup headergroup;
+ private HttpEntity entity;
+ private LinkedList<NameValuePair> parameters;
+ private RequestConfig config;
+
+ RequestBuilder(final String method) {
+ super();
+ this.method = method;
+ }
+
+ RequestBuilder() {
+ this(null);
+ }
+
+ public static RequestBuilder create(final String method) {
+ Args.notBlank(method, "HTTP method");
+ return new RequestBuilder(method);
+ }
+
+ public static RequestBuilder get() {
+ return new RequestBuilder(HttpGet.METHOD_NAME);
+ }
+
+ public static RequestBuilder head() {
+ return new RequestBuilder(HttpHead.METHOD_NAME);
+ }
+
+ public static RequestBuilder post() {
+ return new RequestBuilder(HttpPost.METHOD_NAME);
+ }
+
+ public static RequestBuilder put() {
+ return new RequestBuilder(HttpPut.METHOD_NAME);
+ }
+
+ public static RequestBuilder delete() {
+ return new RequestBuilder(HttpDelete.METHOD_NAME);
+ }
+
+ public static RequestBuilder trace() {
+ return new RequestBuilder(HttpTrace.METHOD_NAME);
+ }
+
+ public static RequestBuilder options() {
+ return new RequestBuilder(HttpOptions.METHOD_NAME);
+ }
+
+ public static RequestBuilder copy(final HttpRequest request) {
+ Args.notNull(request, "HTTP request");
+ return new RequestBuilder().doCopy(request);
+ }
+
+ private RequestBuilder doCopy(final HttpRequest request) {
+ if (request == null) {
+ return this;
+ }
+ method = request.getRequestLine().getMethod();
+ version = request.getRequestLine().getProtocolVersion();
+ if (request instanceof HttpUriRequest) {
+ uri = ((HttpUriRequest) request).getURI();
+ } else {
+ uri = URI.create(request.getRequestLine().getUri());
+ }
+ if (headergroup == null) {
+ headergroup = new HeaderGroup();
+ }
+ headergroup.clear();
+ headergroup.setHeaders(request.getAllHeaders());
+ if (request instanceof HttpEntityEnclosingRequest) {
+ entity = ((HttpEntityEnclosingRequest) request).getEntity();
+ } else {
+ entity = null;
+ }
+ if (request instanceof Configurable) {
+ this.config = ((Configurable) request).getConfig();
+ } else {
+ this.config = null;
+ }
+ this.parameters = null;
+ return this;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public ProtocolVersion getVersion() {
+ return version;
+ }
+
+ public RequestBuilder setVersion(final ProtocolVersion version) {
+ this.version = version;
+ return this;
+ }
+
+ public URI getUri() {
+ return uri;
+ }
+
+ public RequestBuilder setUri(final URI uri) {
+ this.uri = uri;
+ return this;
+ }
+
+ public RequestBuilder setUri(final String uri) {
+ this.uri = uri != null ? URI.create(uri) : null;
+ return this;
+ }
+
+ public Header getFirstHeader(final String name) {
+ return headergroup != null ? headergroup.getFirstHeader(name) : null;
+ }
+
+ public Header getLastHeader(final String name) {
+ return headergroup != null ? headergroup.getLastHeader(name) : null;
+ }
+
+ public Header[] getHeaders(final String name) {
+ return headergroup != null ? headergroup.getHeaders(name) : null;
+ }
+
+ public RequestBuilder addHeader(final Header header) {
+ if (headergroup == null) {
+ headergroup = new HeaderGroup();
+ }
+ headergroup.addHeader(header);
+ return this;
+ }
+
+ public RequestBuilder addHeader(final String name, final String value) {
+ if (headergroup == null) {
+ headergroup = new HeaderGroup();
+ }
+ this.headergroup.addHeader(new BasicHeader(name, value));
+ return this;
+ }
+
+ public RequestBuilder removeHeader(final Header header) {
+ if (headergroup == null) {
+ headergroup = new HeaderGroup();
+ }
+ headergroup.removeHeader(header);
+ return this;
+ }
+
+ public RequestBuilder removeHeaders(final String name) {
+ if (name == null || headergroup == null) {
+ return this;
+ }
+ for (final HeaderIterator i = headergroup.iterator(); i.hasNext(); ) {
+ final Header header = i.nextHeader();
+ if (name.equalsIgnoreCase(header.getName())) {
+ i.remove();
+ }
+ }
+ return this;
+ }
+
+ public RequestBuilder setHeader(final Header header) {
+ if (headergroup == null) {
+ headergroup = new HeaderGroup();
+ }
+ this.headergroup.updateHeader(header);
+ return this;
+ }
+
+ public RequestBuilder setHeader(final String name, final String value) {
+ if (headergroup == null) {
+ headergroup = new HeaderGroup();
+ }
+ this.headergroup.updateHeader(new BasicHeader(name, value));
+ return this;
+ }
+
+ public HttpEntity getEntity() {
+ return entity;
+ }
+
+ public RequestBuilder setEntity(final HttpEntity entity) {
+ this.entity = entity;
+ return this;
+ }
+
+ public List<NameValuePair> getParameters() {
+ return parameters != null ? new ArrayList<NameValuePair>(parameters) :
+ new ArrayList<NameValuePair>();
+ }
+
+ public RequestBuilder addParameter(final NameValuePair nvp) {
+ Args.notNull(nvp, "Name value pair");
+ if (parameters == null) {
+ parameters = new LinkedList<NameValuePair>();
+ }
+ parameters.add(nvp);
+ return this;
+ }
+
+ public RequestBuilder addParameter(final String name, final String value) {
+ return addParameter(new BasicNameValuePair(name, value));
+ }
+
+ public RequestBuilder addParameters(final NameValuePair... nvps) {
+ for (final NameValuePair nvp: nvps) {
+ addParameter(nvp);
+ }
+ return this;
+ }
+
+ public RequestConfig getConfig() {
+ return config;
+ }
+
+ public RequestBuilder setConfig(final RequestConfig config) {
+ this.config = config;
+ return this;
+ }
+
+ public HttpUriRequest build() {
+ final HttpRequestBase result;
+ URI uri = this.uri != null ? this.uri : URI.create("/");
+ HttpEntity entity = this.entity;
+ if (parameters != null && !parameters.isEmpty()) {
+ if (entity == null && (HttpPost.METHOD_NAME.equalsIgnoreCase(method)
+ || HttpPut.METHOD_NAME.equalsIgnoreCase(method))) {
+ entity = new UrlEncodedFormEntity(parameters, HTTP.DEF_CONTENT_CHARSET);
+ } else {
+ try {
+ uri = new URIBuilder(uri).addParameters(parameters).build();
+ } catch (final URISyntaxException ex) {
+ // should never happen
+ }
+ }
+ }
+ if (entity == null) {
+ result = new InternalRequest(method);
+ } else {
+ final InternalEntityEclosingRequest request = new InternalEntityEclosingRequest(method);
+ request.setEntity(entity);
+ result = request;
+ }
+ result.setProtocolVersion(this.version);
+ result.setURI(uri);
+ if (this.headergroup != null) {
+ result.setHeaders(this.headergroup.getAllHeaders());
+ }
+ result.setConfig(this.config);
+ return result;
+ }
+
+ static class InternalRequest extends HttpRequestBase {
+
+ private final String method;
+
+ InternalRequest(final String method) {
+ super();
+ this.method = method;
+ }
+
+ @Override
+ public String getMethod() {
+ return this.method;
+ }
+
+ }
+
+ static class InternalEntityEclosingRequest extends HttpEntityEnclosingRequestBase {
+
+ private final String method;
+
+ InternalEntityEclosingRequest(final String method) {
+ super();
+ this.method = method;
+ }
+
+ @Override
+ public String getMethod() {
+ return this.method;
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/package-info.java
new file mode 100644
index 000000000..d8266b2e3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/methods/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Standard HTTP method implementations.
+ */
+package ch.boye.httpclientandroidlib.client.methods;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/package-info.java
new file mode 100644
index 000000000..2d49a2b99
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client HTTP communication APIs.
+ */
+package ch.boye.httpclientandroidlib.client;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AllClientPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AllClientPNames.java
new file mode 100644
index 000000000..aaf591571
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AllClientPNames.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.params;
+
+import ch.boye.httpclientandroidlib.auth.params.AuthPNames;
+import ch.boye.httpclientandroidlib.conn.params.ConnConnectionPNames;
+import ch.boye.httpclientandroidlib.conn.params.ConnManagerPNames;
+import ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames;
+import ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
+
+/**
+ * Collected parameter names for the HttpClient module.
+ * This interface combines the parameter definitions of the HttpClient
+ * module and all dependency modules or informational units.
+ * It does not define additional parameter names, but references
+ * other interfaces defining parameter names.
+ * <br/>
+ * This interface is meant as a navigation aid for developers.
+ * When referring to parameter names, you should use the interfaces
+ * in which the respective constants are actually defined.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use
+ * {@link ch.boye.httpclientandroidlib.client.config.RequestConfig},
+ * {@link ch.boye.httpclientandroidlib.config.ConnectionConfig},
+ * {@link ch.boye.httpclientandroidlib.config.SocketConfig}
+ */
+@Deprecated
+public interface AllClientPNames extends
+ CoreConnectionPNames, CoreProtocolPNames,
+ ClientPNames, AuthPNames, CookieSpecPNames,
+ ConnConnectionPNames, ConnManagerPNames, ConnRoutePNames {
+
+ // no additional definitions
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AuthPolicy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AuthPolicy.java
new file mode 100644
index 000000000..b677ee02f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/AuthPolicy.java
@@ -0,0 +1,79 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.params;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Standard authentication schemes supported by HttpClient.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.AuthSchemes}.
+ */
+@Deprecated
+@Immutable
+public final class AuthPolicy {
+
+ private AuthPolicy() {
+ super();
+ }
+
+ /**
+ * The NTLM scheme is a proprietary Microsoft Windows Authentication
+ * protocol (considered to be the most secure among currently supported
+ * authentication schemes).
+ */
+ public static final String NTLM = "NTLM";
+
+ /**
+ * Digest authentication scheme as defined in RFC2617.
+ */
+ public static final String DIGEST = "Digest";
+
+ /**
+ * Basic authentication scheme as defined in RFC2617 (considered inherently
+ * insecure, but most widely supported)
+ */
+ public static final String BASIC = "Basic";
+
+ /**
+ * SPNEGO Authentication scheme.
+ *
+ * @since 4.1
+ */
+ public static final String SPNEGO = "negotiate";
+
+ /**
+ * Kerberos Authentication scheme.
+ *
+ * @since 4.2
+ */
+ public static final String KERBEROS = "Kerberos";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientPNames.java
new file mode 100644
index 000000000..796ee40fb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientPNames.java
@@ -0,0 +1,133 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.params;
+
+/**
+ * Parameter names for HTTP client parameters.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
+ */
+@Deprecated
+public interface ClientPNames {
+
+ public static final String CONNECTION_MANAGER_FACTORY_CLASS_NAME = "http.connection-manager.factory-class-name";
+
+ /**
+ * Defines whether redirects should be handled automatically
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String HANDLE_REDIRECTS = "http.protocol.handle-redirects";
+
+ /**
+ * Defines whether relative redirects should be rejected. HTTP specification
+ * requires the location value be an absolute URI.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String REJECT_RELATIVE_REDIRECT = "http.protocol.reject-relative-redirect";
+
+ /**
+ * Defines the maximum number of redirects to be followed.
+ * The limit on number of redirects is intended to prevent infinite loops.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String MAX_REDIRECTS = "http.protocol.max-redirects";
+
+ /**
+ * Defines whether circular redirects (redirects to the same location) should be allowed.
+ * The HTTP spec is not sufficiently clear whether circular redirects are permitted,
+ * therefore optionally they can be enabled
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects";
+
+ /**
+ * Defines whether authentication should be handled automatically.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String HANDLE_AUTHENTICATION = "http.protocol.handle-authentication";
+
+ /**
+ * Defines the name of the cookie specification to be used for HTTP state management.
+ * <p>
+ * This parameter expects a value of type {@link String}.
+ * </p>
+ */
+ public static final String COOKIE_POLICY = "http.protocol.cookie-policy";
+
+ /**
+ * Defines the virtual host to be used in the <code>Host</code>
+ * request header instead of the physical host.
+ * <p>
+ * This parameter expects a value of type {@link ch.boye.httpclientandroidlib.HttpHost}.
+ * </p>
+ * If a port is not provided, it will be derived from the request URL.
+ */
+ public static final String VIRTUAL_HOST = "http.virtual-host";
+
+ /**
+ * Defines the request headers to be sent per default with each request.
+ * <p>
+ * This parameter expects a value of type {@link java.util.Collection}. The
+ * collection is expected to contain {@link ch.boye.httpclientandroidlib.Header}s.
+ * </p>
+ */
+ public static final String DEFAULT_HEADERS = "http.default-headers";
+
+ /**
+ * Defines the default host. The default value will be used if the target host is
+ * not explicitly specified in the request URI.
+ * <p>
+ * This parameter expects a value of type {@link ch.boye.httpclientandroidlib.HttpHost}.
+ * </p>
+ */
+ public static final String DEFAULT_HOST = "http.default-host";
+
+ /**
+ * Defines the timeout in milliseconds used when retrieving an instance of
+ * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the
+ * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}.
+ * <p>
+ * This parameter expects a value of type {@link Long}.
+ * <p>
+ * @since 4.2
+ */
+ public static final String CONN_MANAGER_TIMEOUT = "http.conn-manager.timeout";
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientParamBean.java
new file mode 100644
index 000000000..315129d23
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/ClientParamBean.java
@@ -0,0 +1,106 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.params;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate HTTP client parameters using
+ * Java Beans conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
+ */
+@Deprecated
+@NotThreadSafe
+public class ClientParamBean extends HttpAbstractParamBean {
+
+ public ClientParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ /**
+ * @deprecated (4.2) do not use.
+ */
+ @Deprecated
+ public void setConnectionManagerFactoryClassName (final String factory) {
+ params.setParameter(ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME, factory);
+ }
+
+ public void setHandleRedirects (final boolean handle) {
+ params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, handle);
+ }
+
+ public void setRejectRelativeRedirect (final boolean reject) {
+ params.setBooleanParameter(ClientPNames.REJECT_RELATIVE_REDIRECT, reject);
+ }
+
+ public void setMaxRedirects (final int maxRedirects) {
+ params.setIntParameter(ClientPNames.MAX_REDIRECTS, maxRedirects);
+ }
+
+ public void setAllowCircularRedirects (final boolean allow) {
+ params.setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, allow);
+ }
+
+ public void setHandleAuthentication (final boolean handle) {
+ params.setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, handle);
+ }
+
+ public void setCookiePolicy (final String policy) {
+ params.setParameter(ClientPNames.COOKIE_POLICY, policy);
+ }
+
+ public void setVirtualHost (final HttpHost host) {
+ params.setParameter(ClientPNames.VIRTUAL_HOST, host);
+ }
+
+ public void setDefaultHeaders (final Collection <Header> headers) {
+ params.setParameter(ClientPNames.DEFAULT_HEADERS, headers);
+ }
+
+ public void setDefaultHost (final HttpHost host) {
+ params.setParameter(ClientPNames.DEFAULT_HOST, host);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void setConnectionManagerTimeout(final long timeout) {
+ params.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, timeout);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/CookiePolicy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/CookiePolicy.java
new file mode 100644
index 000000000..5c6353b80
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/CookiePolicy.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.params;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Standard cookie specifications supported by HttpClient.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.CookieSpecs}.
+ */
+@Deprecated
+@Immutable
+public final class CookiePolicy {
+
+ /**
+ * The policy that provides high degree of compatibilty
+ * with common cookie management of popular HTTP agents.
+ */
+ public static final String BROWSER_COMPATIBILITY = "compatibility";
+
+ /**
+ * The Netscape cookie draft compliant policy.
+ */
+ public static final String NETSCAPE = "netscape";
+
+ /**
+ * The RFC 2109 compliant policy.
+ */
+ public static final String RFC_2109 = "rfc2109";
+
+ /**
+ * The RFC 2965 compliant policy.
+ */
+ public static final String RFC_2965 = "rfc2965";
+
+ /**
+ * The default 'best match' policy.
+ */
+ public static final String BEST_MATCH = "best-match";
+
+ /**
+ * The policy that ignores cookies.
+ *
+ * @since 4.1-beta1
+ */
+ public static final String IGNORE_COOKIES = "ignoreCookies";
+
+ private CookiePolicy() {
+ super();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParamConfig.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParamConfig.java
new file mode 100644
index 000000000..515d92ca5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParamConfig.java
@@ -0,0 +1,88 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.params;
+
+import java.net.InetAddress;
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.auth.params.AuthPNames;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * @deprecated (4.3) provided for compatibility with {@link HttpParams}. Do not use.
+ *
+ * @since 4.3
+ */
+@Deprecated
+public final class HttpClientParamConfig {
+
+ private HttpClientParamConfig() {
+ }
+
+ @SuppressWarnings("unchecked")
+ public static RequestConfig getRequestConfig(final HttpParams params) {
+ return RequestConfig.custom()
+ .setSocketTimeout(params.getIntParameter(
+ CoreConnectionPNames.SO_TIMEOUT, 0))
+ .setStaleConnectionCheckEnabled(params.getBooleanParameter(
+ CoreConnectionPNames.STALE_CONNECTION_CHECK, true))
+ .setConnectTimeout(params.getIntParameter(
+ CoreConnectionPNames.CONNECTION_TIMEOUT, 0))
+ .setExpectContinueEnabled(params.getBooleanParameter(
+ CoreProtocolPNames.USE_EXPECT_CONTINUE, false))
+ .setProxy((HttpHost) params.getParameter(
+ ConnRoutePNames.DEFAULT_PROXY))
+ .setLocalAddress((InetAddress) params.getParameter(
+ ConnRoutePNames.LOCAL_ADDRESS))
+ .setProxyPreferredAuthSchemes((Collection<String>) params.getParameter(
+ AuthPNames.PROXY_AUTH_PREF))
+ .setTargetPreferredAuthSchemes((Collection<String>) params.getParameter(
+ AuthPNames.TARGET_AUTH_PREF))
+ .setAuthenticationEnabled(params.getBooleanParameter(
+ ClientPNames.HANDLE_AUTHENTICATION, true))
+ .setCircularRedirectsAllowed(params.getBooleanParameter(
+ ClientPNames.ALLOW_CIRCULAR_REDIRECTS, false))
+ .setConnectionRequestTimeout((int) params.getLongParameter(
+ ClientPNames.CONN_MANAGER_TIMEOUT, 0))
+ .setCookieSpec((String) params.getParameter(
+ ClientPNames.COOKIE_POLICY))
+ .setMaxRedirects(params.getIntParameter(
+ ClientPNames.MAX_REDIRECTS, 50))
+ .setRedirectsEnabled(params.getBooleanParameter(
+ ClientPNames.HANDLE_REDIRECTS, true))
+ .setRelativeRedirectsAllowed(!params.getBooleanParameter(
+ ClientPNames.REJECT_RELATIVE_REDIRECT, false))
+ .build();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParams.java
new file mode 100644
index 000000000..b2b2a573e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/HttpClientParams.java
@@ -0,0 +1,116 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.params;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * An adaptor for manipulating HTTP client parameters in {@link HttpParams}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}
+ */
+@Deprecated
+@Immutable
+public class HttpClientParams {
+
+ private HttpClientParams() {
+ super();
+ }
+
+ public static boolean isRedirecting(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getBooleanParameter
+ (ClientPNames.HANDLE_REDIRECTS, true);
+ }
+
+ public static void setRedirecting(final HttpParams params, final boolean value) {
+ Args.notNull(params, "HTTP parameters");
+ params.setBooleanParameter
+ (ClientPNames.HANDLE_REDIRECTS, value);
+ }
+
+ public static boolean isAuthenticating(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getBooleanParameter
+ (ClientPNames.HANDLE_AUTHENTICATION, true);
+ }
+
+ public static void setAuthenticating(final HttpParams params, final boolean value) {
+ Args.notNull(params, "HTTP parameters");
+ params.setBooleanParameter
+ (ClientPNames.HANDLE_AUTHENTICATION, value);
+ }
+
+ public static String getCookiePolicy(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ final String cookiePolicy = (String)
+ params.getParameter(ClientPNames.COOKIE_POLICY);
+ if (cookiePolicy == null) {
+ return CookiePolicy.BEST_MATCH;
+ }
+ return cookiePolicy;
+ }
+
+ public static void setCookiePolicy(final HttpParams params, final String cookiePolicy) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(ClientPNames.COOKIE_POLICY, cookiePolicy);
+ }
+
+ /**
+ * Set the parameter {@code ClientPNames.CONN_MANAGER_TIMEOUT}.
+ *
+ * @since 4.2
+ */
+ public static void setConnectionManagerTimeout(final HttpParams params, final long timeout) {
+ Args.notNull(params, "HTTP parameters");
+ params.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, timeout);
+ }
+
+ /**
+ * Get the connectiion manager timeout value.
+ * This is defined by the parameter {@code ClientPNames.CONN_MANAGER_TIMEOUT}.
+ * Failing that it uses the parameter {@code CoreConnectionPNames.CONNECTION_TIMEOUT}
+ * which defaults to 0 if not defined.
+ *
+ * @since 4.2
+ * @return the timeout value
+ */
+ public static long getConnectionManagerTimeout(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ final Long timeout = (Long) params.getParameter(ClientPNames.CONN_MANAGER_TIMEOUT);
+ if (timeout != null) {
+ return timeout.longValue();
+ }
+ return HttpConnectionParams.getConnectionTimeout(params);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/package-info.java
new file mode 100644
index 000000000..3450f368e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/params/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Deprecated.
+ * @deprecated (4.3).
+ */
+package ch.boye.httpclientandroidlib.client.params;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContext.java
new file mode 100644
index 000000000..1409362f0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContext.java
@@ -0,0 +1,132 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+/**
+ * {@link ch.boye.httpclientandroidlib.protocol.HttpContext} attribute names for
+ * client side HTTP protocol processing.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link HttpClientContext}.
+ */
+@Deprecated
+public interface ClientContext {
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.conn.routing.RouteInfo}
+ * object that represents the actual connection route.
+ *
+ * @since 4.3
+ */
+ public static final String ROUTE = "http.route";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.conn.scheme.Scheme}
+ * object that represents the actual protocol scheme registry.
+ */
+ @Deprecated
+ public static final String SCHEME_REGISTRY = "http.scheme-registry";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
+ * the actual {@link ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry} registry.
+ */
+ public static final String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieSpec}
+ * object that represents the actual cookie specification.
+ */
+ public static final String COOKIE_SPEC = "http.cookie-spec";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieOrigin}
+ * object that represents the actual details of the origin server.
+ */
+ public static final String COOKIE_ORIGIN = "http.cookie-origin";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.CookieStore}
+ * object that represents the actual cookie store.
+ */
+ public static final String COOKIE_STORE = "http.cookie-store";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.CredentialsProvider}
+ * object that represents the actual credentials provider.
+ */
+ public static final String CREDS_PROVIDER = "http.auth.credentials-provider";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.AuthCache} object
+ * that represents the auth scheme cache.
+ */
+ public static final String AUTH_CACHE = "http.auth.auth-cache";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
+ * object that represents the actual target authentication state.
+ */
+ public static final String TARGET_AUTH_STATE = "http.auth.target-scope";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
+ * object that represents the actual proxy authentication state.
+ */
+ public static final String PROXY_AUTH_STATE = "http.auth.proxy-scope";
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ public static final String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
+
+ /**
+ * Attribute name of a {@link java.lang.Object} object that represents
+ * the actual user identity such as user {@link java.security.Principal}.
+ */
+ public static final String USER_TOKEN = "http.user-token";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
+ * the actual {@link ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry} registry.
+ */
+ public static final String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
+
+ public static final String SOCKET_FACTORY_REGISTRY = "http.socket-factory-registry";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.config.RequestConfig} object that
+ * represents the actual request configuration.
+ *
+ * @since 4.3
+ */
+ public static final String REQUEST_CONFIG = "http.request-config";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContextConfigurer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContextConfigurer.java
new file mode 100644
index 000000000..29628a83d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ClientContextConfigurer.java
@@ -0,0 +1,72 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Configuration facade for {@link HttpContext} instances.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link HttpClientContext}
+ */
+@NotThreadSafe
+@Deprecated
+public class ClientContextConfigurer implements ClientContext {
+
+ private final HttpContext context;
+
+ public ClientContextConfigurer (final HttpContext context) {
+ Args.notNull(context, "HTTP context");
+ this.context = context;
+ }
+
+ public void setCookieSpecRegistry(final CookieSpecRegistry registry) {
+ this.context.setAttribute(COOKIESPEC_REGISTRY, registry);
+ }
+
+ public void setAuthSchemeRegistry(final AuthSchemeRegistry registry) {
+ this.context.setAttribute(AUTHSCHEME_REGISTRY, registry);
+ }
+
+ public void setCookieStore(final CookieStore store) {
+ this.context.setAttribute(COOKIE_STORE, store);
+ }
+
+ public void setCredentialsProvider(final CredentialsProvider provider) {
+ this.context.setAttribute(CREDS_PROVIDER, provider);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/HttpClientContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/HttpClientContext.java
new file mode 100644
index 000000000..7b73e8d64
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/HttpClientContext.java
@@ -0,0 +1,249 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.net.URI;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.client.AuthCache;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpCoreContext;
+
+/**
+ * Adaptor class that provides convenience type safe setters and getters
+ * for common {@link HttpContext} attributes used in the course
+ * of HTTP request execution.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class HttpClientContext extends HttpCoreContext {
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.conn.routing.RouteInfo}
+ * object that represents the actual connection route.
+ */
+ public static final String HTTP_ROUTE = "http.route";
+
+ /**
+ * Attribute name of a {@link List} object that represents a collection of all
+ * redirect locations received in the process of request execution.
+ */
+ public static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
+ * the actual {@link CookieSpecProvider} registry.
+ */
+ public static final String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieSpec}
+ * object that represents the actual cookie specification.
+ */
+ public static final String COOKIE_SPEC = "http.cookie-spec";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.cookie.CookieOrigin}
+ * object that represents the actual details of the origin server.
+ */
+ public static final String COOKIE_ORIGIN = "http.cookie-origin";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.CookieStore}
+ * object that represents the actual cookie store.
+ */
+ public static final String COOKIE_STORE = "http.cookie-store";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.CredentialsProvider}
+ * object that represents the actual credentials provider.
+ */
+ public static final String CREDS_PROVIDER = "http.auth.credentials-provider";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.AuthCache} object
+ * that represents the auth scheme cache.
+ */
+ public static final String AUTH_CACHE = "http.auth.auth-cache";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
+ * object that represents the actual target authentication state.
+ */
+ public static final String TARGET_AUTH_STATE = "http.auth.target-scope";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.auth.AuthState}
+ * object that represents the actual proxy authentication state.
+ */
+ public static final String PROXY_AUTH_STATE = "http.auth.proxy-scope";
+
+ /**
+ * Attribute name of a {@link java.lang.Object} object that represents
+ * the actual user identity such as user {@link java.security.Principal}.
+ */
+ public static final String USER_TOKEN = "http.user-token";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.config.Lookup} object that represents
+ * the actual {@link AuthSchemeProvider} registry.
+ */
+ public static final String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.client.config.RequestConfig} object that
+ * represents the actual request configuration.
+ */
+ public static final String REQUEST_CONFIG = "http.request-config";
+
+ public static HttpClientContext adapt(final HttpContext context) {
+ if (context instanceof HttpClientContext) {
+ return (HttpClientContext) context;
+ } else {
+ return new HttpClientContext(context);
+ }
+ }
+
+ public static HttpClientContext create() {
+ return new HttpClientContext(new BasicHttpContext());
+ }
+
+ public HttpClientContext(final HttpContext context) {
+ super(context);
+ }
+
+ public HttpClientContext() {
+ super();
+ }
+
+ public RouteInfo getHttpRoute() {
+ return getAttribute(HTTP_ROUTE, HttpRoute.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<URI> getRedirectLocations() {
+ return getAttribute(REDIRECT_LOCATIONS, List.class);
+ }
+
+ public CookieStore getCookieStore() {
+ return getAttribute(COOKIE_STORE, CookieStore.class);
+ }
+
+ public void setCookieStore(final CookieStore cookieStore) {
+ setAttribute(COOKIE_STORE, cookieStore);
+ }
+
+ public CookieSpec getCookieSpec() {
+ return getAttribute(COOKIE_SPEC, CookieSpec.class);
+ }
+
+ public CookieOrigin getCookieOrigin() {
+ return getAttribute(COOKIE_ORIGIN, CookieOrigin.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> Lookup<T> getLookup(final String name, final Class<T> clazz) {
+ return getAttribute(name, Lookup.class);
+ }
+
+ public Lookup<CookieSpecProvider> getCookieSpecRegistry() {
+ return getLookup(COOKIESPEC_REGISTRY, CookieSpecProvider.class);
+ }
+
+ public void setCookieSpecRegistry(final Lookup<CookieSpecProvider> lookup) {
+ setAttribute(COOKIESPEC_REGISTRY, lookup);
+ }
+
+ public Lookup<AuthSchemeProvider> getAuthSchemeRegistry() {
+ return getLookup(AUTHSCHEME_REGISTRY, AuthSchemeProvider.class);
+ }
+
+ public void setAuthSchemeRegistry(final Lookup<AuthSchemeProvider> lookup) {
+ setAttribute(AUTHSCHEME_REGISTRY, lookup);
+ }
+
+ public CredentialsProvider getCredentialsProvider() {
+ return getAttribute(CREDS_PROVIDER, CredentialsProvider.class);
+ }
+
+ public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
+ setAttribute(CREDS_PROVIDER, credentialsProvider);
+ }
+
+ public AuthCache getAuthCache() {
+ return getAttribute(AUTH_CACHE, AuthCache.class);
+ }
+
+ public void setAuthCache(final AuthCache authCache) {
+ setAttribute(AUTH_CACHE, authCache);
+ }
+
+ public AuthState getTargetAuthState() {
+ return getAttribute(TARGET_AUTH_STATE, AuthState.class);
+ }
+
+ public AuthState getProxyAuthState() {
+ return getAttribute(PROXY_AUTH_STATE, AuthState.class);
+ }
+
+ public <T> T getUserToken(final Class<T> clazz) {
+ return getAttribute(USER_TOKEN, clazz);
+ }
+
+ public Object getUserToken() {
+ return getAttribute(USER_TOKEN);
+ }
+
+ public void setUserToken(final Object obj) {
+ setAttribute(USER_TOKEN, obj);
+ }
+
+ public RequestConfig getRequestConfig() {
+ final RequestConfig config = getAttribute(REQUEST_CONFIG, RequestConfig.class);
+ return config != null ? config : RequestConfig.DEFAULT;
+ }
+
+ public void setRequestConfig(final RequestConfig config) {
+ setAttribute(REQUEST_CONFIG, config);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAcceptEncoding.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAcceptEncoding.java
new file mode 100644
index 000000000..1c0d642d3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAcceptEncoding.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Class responsible for handling Content Encoding requests in HTTP.
+ * <p>
+ * Instances of this class are stateless, therefore they're thread-safe and immutable.
+ *
+ * @see "http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5"
+ *
+ * @since 4.1
+ */
+@Immutable
+public class RequestAcceptEncoding implements HttpRequestInterceptor {
+
+ /**
+ * Adds the header {@code "Accept-Encoding: gzip,deflate"} to the request.
+ */
+ public void process(
+ final HttpRequest request,
+ final HttpContext context) throws HttpException, IOException {
+
+ /* Signal support for Accept-Encoding transfer encodings. */
+ if (!request.containsHeader("Accept-Encoding")) {
+ request.addHeader("Accept-Encoding", "gzip,deflate");
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAddCookies.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAddCookies.java
new file mode 100644
index 000000000..ad2768043
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAddCookies.java
@@ -0,0 +1,204 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.client.config.CookieSpecs;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.cookie.SetCookie2;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+/**
+ * Request interceptor that matches cookies available in the current
+ * {@link CookieStore} to the request being executed and generates
+ * corresponding <code>Cookie</code> request headers.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RequestAddCookies implements HttpRequestInterceptor {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public RequestAddCookies() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase("CONNECT")) {
+ return;
+ }
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ // Obtain cookie store
+ final CookieStore cookieStore = clientContext.getCookieStore();
+ if (cookieStore == null) {
+ this.log.debug("Cookie store not specified in HTTP context");
+ return;
+ }
+
+ // Obtain the registry of cookie specs
+ final Lookup<CookieSpecProvider> registry = clientContext.getCookieSpecRegistry();
+ if (registry == null) {
+ this.log.debug("CookieSpec registry not specified in HTTP context");
+ return;
+ }
+
+ // Obtain the target host, possibly virtual (required)
+ final HttpHost targetHost = clientContext.getTargetHost();
+ if (targetHost == null) {
+ this.log.debug("Target host not set in the context");
+ return;
+ }
+
+ // Obtain the route (required)
+ final RouteInfo route = clientContext.getHttpRoute();
+ if (route == null) {
+ this.log.debug("Connection route not set in the context");
+ return;
+ }
+
+ final RequestConfig config = clientContext.getRequestConfig();
+ String policy = config.getCookieSpec();
+ if (policy == null) {
+ policy = CookieSpecs.BEST_MATCH;
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("CookieSpec selected: " + policy);
+ }
+
+ URI requestURI = null;
+ if (request instanceof HttpUriRequest) {
+ requestURI = ((HttpUriRequest) request).getURI();
+ } else {
+ try {
+ requestURI = new URI(request.getRequestLine().getUri());
+ } catch (final URISyntaxException ignore) {
+ }
+ }
+ final String path = requestURI != null ? requestURI.getPath() : null;
+ final String hostName = targetHost.getHostName();
+ int port = targetHost.getPort();
+ if (port < 0) {
+ port = route.getTargetHost().getPort();
+ }
+
+ final CookieOrigin cookieOrigin = new CookieOrigin(
+ hostName,
+ port >= 0 ? port : 0,
+ !TextUtils.isEmpty(path) ? path : "/",
+ route.isSecure());
+
+ // Get an instance of the selected cookie policy
+ final CookieSpecProvider provider = registry.lookup(policy);
+ if (provider == null) {
+ throw new HttpException("Unsupported cookie policy: " + policy);
+ }
+ final CookieSpec cookieSpec = provider.create(clientContext);
+ // Get all cookies available in the HTTP state
+ final List<Cookie> cookies = new ArrayList<Cookie>(cookieStore.getCookies());
+ // Find cookies matching the given origin
+ final List<Cookie> matchedCookies = new ArrayList<Cookie>();
+ final Date now = new Date();
+ for (final Cookie cookie : cookies) {
+ if (!cookie.isExpired(now)) {
+ if (cookieSpec.match(cookie, cookieOrigin)) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Cookie " + cookie + " match " + cookieOrigin);
+ }
+ matchedCookies.add(cookie);
+ }
+ } else {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Cookie " + cookie + " expired");
+ }
+ }
+ }
+ // Generate Cookie request headers
+ if (!matchedCookies.isEmpty()) {
+ final List<Header> headers = cookieSpec.formatCookies(matchedCookies);
+ for (final Header header : headers) {
+ request.addHeader(header);
+ }
+ }
+
+ final int ver = cookieSpec.getVersion();
+ if (ver > 0) {
+ boolean needVersionHeader = false;
+ for (final Cookie cookie : matchedCookies) {
+ if (ver != cookie.getVersion() || !(cookie instanceof SetCookie2)) {
+ needVersionHeader = true;
+ }
+ }
+
+ if (needVersionHeader) {
+ final Header header = cookieSpec.getVersionHeader();
+ if (header != null) {
+ // Advertise cookie version support
+ request.addHeader(header);
+ }
+ }
+ }
+
+ // Stick the CookieSpec and CookieOrigin instances to the HTTP context
+ // so they could be obtained by the response interceptor
+ context.setAttribute(HttpClientContext.COOKIE_SPEC, cookieSpec);
+ context.setAttribute(HttpClientContext.COOKIE_ORIGIN, cookieOrigin);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthCache.java
new file mode 100644
index 000000000..08102cfc8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthCache.java
@@ -0,0 +1,147 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthProtocolState;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.client.AuthCache;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Request interceptor that can preemptively authenticate against known hosts,
+ * if there is a cached {@link AuthScheme} instance in the local
+ * {@link AuthCache} associated with the given target or proxy host.
+ *
+ * @since 4.1
+ */
+@Immutable
+public class RequestAuthCache implements HttpRequestInterceptor {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public RequestAuthCache() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ final AuthCache authCache = clientContext.getAuthCache();
+ if (authCache == null) {
+ this.log.debug("Auth cache not set in the context");
+ return;
+ }
+
+ final CredentialsProvider credsProvider = clientContext.getCredentialsProvider();
+ if (credsProvider == null) {
+ this.log.debug("Credentials provider not set in the context");
+ return;
+ }
+
+ final RouteInfo route = clientContext.getHttpRoute();
+ if (route == null) {
+ this.log.debug("Route info not set in the context");
+ return;
+ }
+
+ HttpHost target = clientContext.getTargetHost();
+ if (target == null) {
+ this.log.debug("Target host not set in the context");
+ return;
+ }
+
+ if (target.getPort() < 0) {
+ target = new HttpHost(
+ target.getHostName(),
+ route.getTargetHost().getPort(),
+ target.getSchemeName());
+ }
+
+ final AuthState targetState = clientContext.getTargetAuthState();
+ if (targetState != null && targetState.getState() == AuthProtocolState.UNCHALLENGED) {
+ final AuthScheme authScheme = authCache.get(target);
+ if (authScheme != null) {
+ doPreemptiveAuth(target, authScheme, targetState, credsProvider);
+ }
+ }
+
+ final HttpHost proxy = route.getProxyHost();
+ final AuthState proxyState = clientContext.getProxyAuthState();
+ if (proxy != null && proxyState != null && proxyState.getState() == AuthProtocolState.UNCHALLENGED) {
+ final AuthScheme authScheme = authCache.get(proxy);
+ if (authScheme != null) {
+ doPreemptiveAuth(proxy, authScheme, proxyState, credsProvider);
+ }
+ }
+ }
+
+ private void doPreemptiveAuth(
+ final HttpHost host,
+ final AuthScheme authScheme,
+ final AuthState authState,
+ final CredentialsProvider credsProvider) {
+ final String schemeName = authScheme.getSchemeName();
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Re-using cached '" + schemeName + "' auth scheme for " + host);
+ }
+
+ final AuthScope authScope = new AuthScope(host, AuthScope.ANY_REALM, schemeName);
+ final Credentials creds = credsProvider.getCredentials(authScope);
+
+ if (creds != null) {
+ if ("BASIC".equalsIgnoreCase(authScheme.getSchemeName())) {
+ authState.setState(AuthProtocolState.CHALLENGED);
+ } else {
+ authState.setState(AuthProtocolState.SUCCESS);
+ }
+ authState.update(authScheme, creds);
+ } else {
+ this.log.debug("No credentials for preemptive authentication");
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthenticationBase.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthenticationBase.java
new file mode 100644
index 000000000..19e07054b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestAuthenticationBase.java
@@ -0,0 +1,126 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.util.Queue;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.auth.AuthOption;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.ContextAwareAuthScheme;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+@Deprecated
+abstract class RequestAuthenticationBase implements HttpRequestInterceptor {
+
+ final HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public RequestAuthenticationBase() {
+ super();
+ }
+
+ void process(
+ final AuthState authState,
+ final HttpRequest request,
+ final HttpContext context) {
+ AuthScheme authScheme = authState.getAuthScheme();
+ Credentials creds = authState.getCredentials();
+ switch (authState.getState()) {
+ case FAILURE:
+ return;
+ case SUCCESS:
+ ensureAuthScheme(authScheme);
+ if (authScheme.isConnectionBased()) {
+ return;
+ }
+ break;
+ case CHALLENGED:
+ final Queue<AuthOption> authOptions = authState.getAuthOptions();
+ if (authOptions != null) {
+ while (!authOptions.isEmpty()) {
+ final AuthOption authOption = authOptions.remove();
+ authScheme = authOption.getAuthScheme();
+ creds = authOption.getCredentials();
+ authState.update(authScheme, creds);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Generating response to an authentication challenge using "
+ + authScheme.getSchemeName() + " scheme");
+ }
+ try {
+ final Header header = authenticate(authScheme, creds, request, context);
+ request.addHeader(header);
+ break;
+ } catch (final AuthenticationException ex) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn(authScheme + " authentication error: " + ex.getMessage());
+ }
+ }
+ }
+ return;
+ } else {
+ ensureAuthScheme(authScheme);
+ }
+ }
+ if (authScheme != null) {
+ try {
+ final Header header = authenticate(authScheme, creds, request, context);
+ request.addHeader(header);
+ } catch (final AuthenticationException ex) {
+ if (this.log.isErrorEnabled()) {
+ this.log.error(authScheme + " authentication error: " + ex.getMessage());
+ }
+ }
+ }
+ }
+
+ private void ensureAuthScheme(final AuthScheme authScheme) {
+ Asserts.notNull(authScheme, "Auth scheme");
+ }
+
+ private Header authenticate(
+ final AuthScheme authScheme,
+ final Credentials creds,
+ final HttpRequest request,
+ final HttpContext context) throws AuthenticationException {
+ Asserts.notNull(authScheme, "Auth scheme");
+ if (authScheme instanceof ContextAwareAuthScheme) {
+ return ((ContextAwareAuthScheme) authScheme).authenticate(creds, request, context);
+ } else {
+ return authScheme.authenticate(creds, request);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestClientConnControl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestClientConnControl.java
new file mode 100644
index 000000000..714b2859b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestClientConnControl.java
@@ -0,0 +1,92 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.routing.RouteInfo;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * This protocol interceptor is responsible for adding <code>Connection</code>
+ * or <code>Proxy-Connection</code> headers to the outgoing requests, which
+ * is essential for managing persistence of <code>HTTP/1.0</code> connections.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RequestClientConnControl implements HttpRequestInterceptor {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private static final String PROXY_CONN_DIRECTIVE = "Proxy-Connection";
+
+ public RequestClientConnControl() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase("CONNECT")) {
+ request.setHeader(PROXY_CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
+ return;
+ }
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ // Obtain the client connection (required)
+ final RouteInfo route = clientContext.getHttpRoute();
+ if (route == null) {
+ this.log.debug("Connection route not set in the context");
+ return;
+ }
+
+ if (route.getHopCount() == 1 || route.isTunnelled()) {
+ if (!request.containsHeader(HTTP.CONN_DIRECTIVE)) {
+ request.addHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
+ }
+ }
+ if (route.getHopCount() == 2 && !route.isTunnelled()) {
+ if (!request.containsHeader(PROXY_CONN_DIRECTIVE)) {
+ request.addHeader(PROXY_CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestDefaultHeaders.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestDefaultHeaders.java
new file mode 100644
index 000000000..c4414f1f4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestDefaultHeaders.java
@@ -0,0 +1,89 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.params.ClientPNames;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Request interceptor that adds default request headers.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@Immutable
+public class RequestDefaultHeaders implements HttpRequestInterceptor {
+
+ private final Collection<? extends Header> defaultHeaders;
+
+ /**
+ * @since 4.3
+ */
+ public RequestDefaultHeaders(final Collection<? extends Header> defaultHeaders) {
+ super();
+ this.defaultHeaders = defaultHeaders;
+ }
+
+ public RequestDefaultHeaders() {
+ this(null);
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase("CONNECT")) {
+ return;
+ }
+
+ // Add default headers
+ @SuppressWarnings("unchecked")
+ Collection<? extends Header> defHeaders = (Collection<? extends Header>)
+ request.getParams().getParameter(ClientPNames.DEFAULT_HEADERS);
+ if (defHeaders == null) {
+ defHeaders = this.defaultHeaders;
+ }
+
+ if (defHeaders != null) {
+ for (final Header defHeader : defHeaders) {
+ request.addHeader(defHeader);
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestExpectContinue.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestExpectContinue.java
new file mode 100644
index 000000000..237004f0f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestExpectContinue.java
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * RequestExpectContinue is responsible for enabling the 'expect-continue'
+ * handshake by adding <code>Expect</code> header.
+ * <p/>
+ * This interceptor takes into account {@link RequestConfig#isExpectContinueEnabled()}
+ * setting.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class RequestExpectContinue implements HttpRequestInterceptor {
+
+ public RequestExpectContinue() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+
+ if (!request.containsHeader(HTTP.EXPECT_DIRECTIVE)) {
+ if (request instanceof HttpEntityEnclosingRequest) {
+ final ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
+ final HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
+ // Do not send the expect header if request body is known to be empty
+ if (entity != null
+ && entity.getContentLength() != 0 && !ver.lessEquals(HttpVersion.HTTP_1_0)) {
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+ final RequestConfig config = clientContext.getRequestConfig();
+ if (config.isExpectContinueEnabled()) {
+ request.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestProxyAuthentication.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestProxyAuthentication.java
new file mode 100644
index 000000000..e67468ff8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestProxyAuthentication.java
@@ -0,0 +1,92 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.conn.HttpRoutedConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Generates authentication header for the proxy host, if required,
+ * based on the actual state of the HTTP authentication context.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.impl.auth.HttpAuthenticator}.
+ */
+@Deprecated
+@Immutable
+public class RequestProxyAuthentication extends RequestAuthenticationBase {
+
+ public RequestProxyAuthentication() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ if (request.containsHeader(AUTH.PROXY_AUTH_RESP)) {
+ return;
+ }
+
+ final HttpRoutedConnection conn = (HttpRoutedConnection) context.getAttribute(
+ ExecutionContext.HTTP_CONNECTION);
+ if (conn == null) {
+ this.log.debug("HTTP connection not set in the context");
+ return;
+ }
+ final HttpRoute route = conn.getRoute();
+ if (route.isTunnelled()) {
+ return;
+ }
+
+ // Obtain authentication state
+ final AuthState authState = (AuthState) context.getAttribute(
+ ClientContext.PROXY_AUTH_STATE);
+ if (authState == null) {
+ this.log.debug("Proxy auth state not set in the context");
+ return;
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Proxy auth state: " + authState.getState());
+ }
+ process(authState, request, context);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestTargetAuthentication.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestTargetAuthentication.java
new file mode 100644
index 000000000..dd5c52597
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/RequestTargetAuthentication.java
@@ -0,0 +1,83 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Generates authentication header for the target host, if required,
+ * based on the actual state of the HTTP authentication context.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.impl.auth.HttpAuthenticator}.
+ */
+@Deprecated
+@Immutable
+public class RequestTargetAuthentication extends RequestAuthenticationBase {
+
+ public RequestTargetAuthentication() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase("CONNECT")) {
+ return;
+ }
+
+ if (request.containsHeader(AUTH.WWW_AUTH_RESP)) {
+ return;
+ }
+
+ // Obtain authentication state
+ final AuthState authState = (AuthState) context.getAttribute(
+ ClientContext.TARGET_AUTH_STATE);
+ if (authState == null) {
+ this.log.debug("Target auth state not set in the context");
+ return;
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Target auth state: " + authState.getState());
+ }
+ process(authState, request, context);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseAuthCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseAuthCache.java
new file mode 100644
index 000000000..fc51012f6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseAuthCache.java
@@ -0,0 +1,151 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.client.AuthCache;
+import ch.boye.httpclientandroidlib.client.params.AuthPolicy;
+import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.impl.client.BasicAuthCache;
+import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Response interceptor that adds successfully completed {@link AuthScheme}s
+ * to the local {@link AuthCache} instance. Cached {@link AuthScheme}s can be
+ * re-used when executing requests against known hosts, thus avoiding
+ * additional authentication round-trips.
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.client.AuthenticationStrategy}
+ */
+@Immutable
+@Deprecated
+public class ResponseAuthCache implements HttpResponseInterceptor {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public ResponseAuthCache() {
+ super();
+ }
+
+ public void process(final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP request");
+ Args.notNull(context, "HTTP context");
+ AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
+
+ HttpHost target = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
+ final AuthState targetState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
+ if (target != null && targetState != null) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Target auth state: " + targetState.getState());
+ }
+ if (isCachable(targetState)) {
+ final SchemeRegistry schemeRegistry = (SchemeRegistry) context.getAttribute(
+ ClientContext.SCHEME_REGISTRY);
+ if (target.getPort() < 0) {
+ final Scheme scheme = schemeRegistry.getScheme(target);
+ target = new HttpHost(target.getHostName(),
+ scheme.resolvePort(target.getPort()), target.getSchemeName());
+ }
+ if (authCache == null) {
+ authCache = new BasicAuthCache();
+ context.setAttribute(ClientContext.AUTH_CACHE, authCache);
+ }
+ switch (targetState.getState()) {
+ case CHALLENGED:
+ cache(authCache, target, targetState.getAuthScheme());
+ break;
+ case FAILURE:
+ uncache(authCache, target, targetState.getAuthScheme());
+ }
+ }
+ }
+
+ final HttpHost proxy = (HttpHost) context.getAttribute(ExecutionContext.HTTP_PROXY_HOST);
+ final AuthState proxyState = (AuthState) context.getAttribute(ClientContext.PROXY_AUTH_STATE);
+ if (proxy != null && proxyState != null) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Proxy auth state: " + proxyState.getState());
+ }
+ if (isCachable(proxyState)) {
+ if (authCache == null) {
+ authCache = new BasicAuthCache();
+ context.setAttribute(ClientContext.AUTH_CACHE, authCache);
+ }
+ switch (proxyState.getState()) {
+ case CHALLENGED:
+ cache(authCache, proxy, proxyState.getAuthScheme());
+ break;
+ case FAILURE:
+ uncache(authCache, proxy, proxyState.getAuthScheme());
+ }
+ }
+ }
+ }
+
+ private boolean isCachable(final AuthState authState) {
+ final AuthScheme authScheme = authState.getAuthScheme();
+ if (authScheme == null || !authScheme.isComplete()) {
+ return false;
+ }
+ final String schemeName = authScheme.getSchemeName();
+ return schemeName.equalsIgnoreCase(AuthPolicy.BASIC) ||
+ schemeName.equalsIgnoreCase(AuthPolicy.DIGEST);
+ }
+
+ private void cache(final AuthCache authCache, final HttpHost host, final AuthScheme authScheme) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Caching '" + authScheme.getSchemeName() +
+ "' auth scheme for " + host);
+ }
+ authCache.put(host, authScheme);
+ }
+
+ private void uncache(final AuthCache authCache, final HttpHost host, final AuthScheme authScheme) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Removing from cache '" + authScheme.getSchemeName() +
+ "' auth scheme for " + host);
+ }
+ authCache.remove(host);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseContentEncoding.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseContentEncoding.java
new file mode 100644
index 000000000..df3ee4457
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseContentEncoding.java
@@ -0,0 +1,110 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.entity.DeflateDecompressingEntity;
+import ch.boye.httpclientandroidlib.client.entity.GzipDecompressingEntity;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link HttpResponseInterceptor} responsible for processing Content-Encoding
+ * responses.
+ * <p>
+ * Instances of this class are stateless and immutable, therefore threadsafe.
+ *
+ * @since 4.1
+ *
+ */
+@Immutable
+public class ResponseContentEncoding implements HttpResponseInterceptor {
+
+ public static final String UNCOMPRESSED = "http.client.response.uncompressed";
+
+ /**
+ * Handles the following {@code Content-Encoding}s by
+ * using the appropriate decompressor to wrap the response Entity:
+ * <ul>
+ * <li>gzip - see {@link GzipDecompressingEntity}</li>
+ * <li>deflate - see {@link DeflateDecompressingEntity}</li>
+ * <li>identity - no action needed</li>
+ * </ul>
+ *
+ * @param response the response which contains the entity
+ * @param context not currently used
+ *
+ * @throws HttpException if the {@code Content-Encoding} is none of the above
+ */
+ public void process(
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
+ final HttpEntity entity = response.getEntity();
+
+ // entity can be null in case of 304 Not Modified, 204 No Content or similar
+ // check for zero length entity.
+ if (entity != null && entity.getContentLength() != 0) {
+ final Header ceheader = entity.getContentEncoding();
+ if (ceheader != null) {
+ final HeaderElement[] codecs = ceheader.getElements();
+ boolean uncompressed = false;
+ for (final HeaderElement codec : codecs) {
+ final String codecname = codec.getName().toLowerCase(Locale.ENGLISH);
+ if ("gzip".equals(codecname) || "x-gzip".equals(codecname)) {
+ response.setEntity(new GzipDecompressingEntity(response.getEntity()));
+ uncompressed = true;
+ break;
+ } else if ("deflate".equals(codecname)) {
+ response.setEntity(new DeflateDecompressingEntity(response.getEntity()));
+ uncompressed = true;
+ break;
+ } else if ("identity".equals(codecname)) {
+
+ /* Don't need to transform the content - no-op */
+ return;
+ } else {
+ throw new HttpException("Unsupported Content-Coding: " + codec.getName());
+ }
+ }
+ if (uncompressed) {
+ response.removeHeaders("Content-Length");
+ response.removeHeaders("Content-Encoding");
+ response.removeHeaders("Content-MD5");
+ }
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseProcessCookies.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseProcessCookies.java
new file mode 100644
index 000000000..06827bfdc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/ResponseProcessCookies.java
@@ -0,0 +1,156 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.protocol;
+
+import java.io.IOException;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SM;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Response interceptor that populates the current {@link CookieStore} with data
+ * contained in response cookies received in the given the HTTP response.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ResponseProcessCookies implements HttpResponseInterceptor {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public ResponseProcessCookies() {
+ super();
+ }
+
+ public void process(final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ // Obtain actual CookieSpec instance
+ final CookieSpec cookieSpec = clientContext.getCookieSpec();
+ if (cookieSpec == null) {
+ this.log.debug("Cookie spec not specified in HTTP context");
+ return;
+ }
+ // Obtain cookie store
+ final CookieStore cookieStore = clientContext.getCookieStore();
+ if (cookieStore == null) {
+ this.log.debug("Cookie store not specified in HTTP context");
+ return;
+ }
+ // Obtain actual CookieOrigin instance
+ final CookieOrigin cookieOrigin = clientContext.getCookieOrigin();
+ if (cookieOrigin == null) {
+ this.log.debug("Cookie origin not specified in HTTP context");
+ return;
+ }
+ HeaderIterator it = response.headerIterator(SM.SET_COOKIE);
+ processCookies(it, cookieSpec, cookieOrigin, cookieStore);
+
+ // see if the cookie spec supports cookie versioning.
+ if (cookieSpec.getVersion() > 0) {
+ // process set-cookie2 headers.
+ // Cookie2 will replace equivalent Cookie instances
+ it = response.headerIterator(SM.SET_COOKIE2);
+ processCookies(it, cookieSpec, cookieOrigin, cookieStore);
+ }
+ }
+
+ private void processCookies(
+ final HeaderIterator iterator,
+ final CookieSpec cookieSpec,
+ final CookieOrigin cookieOrigin,
+ final CookieStore cookieStore) {
+ while (iterator.hasNext()) {
+ final Header header = iterator.nextHeader();
+ try {
+ final List<Cookie> cookies = cookieSpec.parse(header, cookieOrigin);
+ for (final Cookie cookie : cookies) {
+ try {
+ cookieSpec.validate(cookie, cookieOrigin);
+ cookieStore.addCookie(cookie);
+
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Cookie accepted [" + formatCooke(cookie) + "]");
+ }
+ } catch (final MalformedCookieException ex) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Cookie rejected [" + formatCooke(cookie) + "] "
+ + ex.getMessage());
+ }
+ }
+ }
+ } catch (final MalformedCookieException ex) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Invalid cookie header: \""
+ + header + "\". " + ex.getMessage());
+ }
+ }
+ }
+ }
+
+ private static String formatCooke(final Cookie cookie) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append(cookie.getName());
+ buf.append("=\"");
+ String v = cookie.getValue();
+ if (v.length() > 100) {
+ v = v.substring(0, 100) + "...";
+ }
+ buf.append(v);
+ buf.append("\"");
+ buf.append(", version:");
+ buf.append(Integer.toString(cookie.getVersion()));
+ buf.append(", domain:");
+ buf.append(cookie.getDomain());
+ buf.append(", path:");
+ buf.append(cookie.getPath());
+ buf.append(", expiry:");
+ buf.append(cookie.getExpiryDate());
+ return buf.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/package-info.java
new file mode 100644
index 000000000..a585e614d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/protocol/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client specific HTTP protocol handlers.
+ */
+package ch.boye.httpclientandroidlib.client.protocol;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/CloneUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/CloneUtils.java
new file mode 100644
index 000000000..67f70ee07
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/CloneUtils.java
@@ -0,0 +1,86 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * A collection of utilities to workaround limitations of Java clone framework.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class CloneUtils {
+
+ /**
+ * @since 4.3
+ */
+ public static <T> T cloneObject(final T obj) throws CloneNotSupportedException {
+ if (obj == null) {
+ return null;
+ }
+ if (obj instanceof Cloneable) {
+ final Class<?> clazz = obj.getClass ();
+ final Method m;
+ try {
+ m = clazz.getMethod("clone", (Class[]) null);
+ } catch (final NoSuchMethodException ex) {
+ throw new NoSuchMethodError(ex.getMessage());
+ }
+ try {
+ @SuppressWarnings("unchecked") // OK because clone() preserves the class
+ final T result = (T) m.invoke(obj, (Object []) null);
+ return result;
+ } catch (final InvocationTargetException ex) {
+ final Throwable cause = ex.getCause();
+ if (cause instanceof CloneNotSupportedException) {
+ throw ((CloneNotSupportedException) cause);
+ } else {
+ throw new Error("Unexpected exception", cause);
+ }
+ } catch (final IllegalAccessException ex) {
+ throw new IllegalAccessError(ex.getMessage());
+ }
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+
+ public static Object clone(final Object obj) throws CloneNotSupportedException {
+ return cloneObject(obj);
+ }
+
+ /**
+ * This class should not be instantiated.
+ */
+ private CloneUtils() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/DateUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/DateUtils.java
new file mode 100644
index 000000000..e337923d3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/DateUtils.java
@@ -0,0 +1,250 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.lang.ref.SoftReference;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A utility class for parsing and formatting HTTP dates as used in cookies and
+ * other headers. This class handles dates as defined by RFC 2616 section
+ * 3.3.1 as well as some other common non-standard formats.
+ *
+ * @since 4.3
+ */
+@Immutable
+public final class DateUtils {
+
+ /**
+ * Date format pattern used to parse HTTP date headers in RFC 1123 format.
+ */
+ public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
+
+ /**
+ * Date format pattern used to parse HTTP date headers in RFC 1036 format.
+ */
+ public static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
+
+ /**
+ * Date format pattern used to parse HTTP date headers in ANSI C
+ * <code>asctime()</code> format.
+ */
+ public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
+
+ private static final String[] DEFAULT_PATTERNS = new String[] {
+ PATTERN_RFC1123,
+ PATTERN_RFC1036,
+ PATTERN_ASCTIME
+ };
+
+ private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
+
+ public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
+ static {
+ final Calendar calendar = Calendar.getInstance();
+ calendar.setTimeZone(GMT);
+ calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
+ }
+
+ /**
+ * Parses a date value. The formats used for parsing the date value are retrieved from
+ * the default http params.
+ *
+ * @param dateValue the date value to parse
+ *
+ * @return the parsed date or null if input could not be parsed
+ */
+ public static Date parseDate(final String dateValue) {
+ return parseDate(dateValue, null, null);
+ }
+
+ /**
+ * Parses the date value using the given date formats.
+ *
+ * @param dateValue the date value to parse
+ * @param dateFormats the date formats to use
+ *
+ * @return the parsed date or null if input could not be parsed
+ */
+ public static Date parseDate(final String dateValue, final String[] dateFormats) {
+ return parseDate(dateValue, dateFormats, null);
+ }
+
+ /**
+ * Parses the date value using the given date formats.
+ *
+ * @param dateValue the date value to parse
+ * @param dateFormats the date formats to use
+ * @param startDate During parsing, two digit years will be placed in the range
+ * <code>startDate</code> to <code>startDate + 100 years</code>. This value may
+ * be <code>null</code>. When <code>null</code> is given as a parameter, year
+ * <code>2000</code> will be used.
+ *
+ * @return the parsed date or null if input could not be parsed
+ */
+ public static Date parseDate(
+ final String dateValue,
+ final String[] dateFormats,
+ final Date startDate) {
+ Args.notNull(dateValue, "Date value");
+ final String[] localDateFormats = dateFormats != null ? dateFormats : DEFAULT_PATTERNS;
+ final Date localStartDate = startDate != null ? startDate : DEFAULT_TWO_DIGIT_YEAR_START;
+ String v = dateValue;
+ // trim single quotes around date if present
+ // see issue #5279
+ if (v.length() > 1 && v.startsWith("'") && v.endsWith("'")) {
+ v = v.substring (1, v.length() - 1);
+ }
+
+ for (final String dateFormat : localDateFormats) {
+ final SimpleDateFormat dateParser = DateFormatHolder.formatFor(dateFormat);
+ dateParser.set2DigitYearStart(localStartDate);
+ final ParsePosition pos = new ParsePosition(0);
+ final Date result = dateParser.parse(v, pos);
+ if (pos.getIndex() != 0) {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Formats the given date according to the RFC 1123 pattern.
+ *
+ * @param date The date to format.
+ * @return An RFC 1123 formatted date string.
+ *
+ * @see #PATTERN_RFC1123
+ */
+ public static String formatDate(final Date date) {
+ return formatDate(date, PATTERN_RFC1123);
+ }
+
+ /**
+ * Formats the given date according to the specified pattern. The pattern
+ * must conform to that used by the {@link SimpleDateFormat simple date
+ * format} class.
+ *
+ * @param date The date to format.
+ * @param pattern The pattern to use for formatting the date.
+ * @return A formatted date string.
+ *
+ * @throws IllegalArgumentException If the given date pattern is invalid.
+ *
+ * @see SimpleDateFormat
+ */
+ public static String formatDate(final Date date, final String pattern) {
+ Args.notNull(date, "Date");
+ Args.notNull(pattern, "Pattern");
+ final SimpleDateFormat formatter = DateFormatHolder.formatFor(pattern);
+ return formatter.format(date);
+ }
+
+ /**
+ * Clears thread-local variable containing {@link java.text.DateFormat} cache.
+ *
+ * @since 4.3
+ */
+ public static void clearThreadLocal() {
+ DateFormatHolder.clearThreadLocal();
+ }
+
+ /** This class should not be instantiated. */
+ private DateUtils() {
+ }
+
+ /**
+ * A factory for {@link SimpleDateFormat}s. The instances are stored in a
+ * threadlocal way because SimpleDateFormat is not threadsafe as noted in
+ * {@link SimpleDateFormat its javadoc}.
+ *
+ */
+ final static class DateFormatHolder {
+
+ private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>
+ THREADLOCAL_FORMATS = new ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>() {
+
+ @Override
+ protected SoftReference<Map<String, SimpleDateFormat>> initialValue() {
+ return new SoftReference<Map<String, SimpleDateFormat>>(
+ new HashMap<String, SimpleDateFormat>());
+ }
+
+ };
+
+ /**
+ * creates a {@link SimpleDateFormat} for the requested format string.
+ *
+ * @param pattern
+ * a non-<code>null</code> format String according to
+ * {@link SimpleDateFormat}. The format is not checked against
+ * <code>null</code> since all paths go through
+ * {@link DateUtils}.
+ * @return the requested format. This simple dateformat should not be used
+ * to {@link SimpleDateFormat#applyPattern(String) apply} to a
+ * different pattern.
+ */
+ public static SimpleDateFormat formatFor(final String pattern) {
+ final SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get();
+ Map<String, SimpleDateFormat> formats = ref.get();
+ if (formats == null) {
+ formats = new HashMap<String, SimpleDateFormat>();
+ THREADLOCAL_FORMATS.set(
+ new SoftReference<Map<String, SimpleDateFormat>>(formats));
+ }
+
+ SimpleDateFormat format = formats.get(pattern);
+ if (format == null) {
+ format = new SimpleDateFormat(pattern, Locale.US);
+ format.setTimeZone(TimeZone.getTimeZone("GMT"));
+ formats.put(pattern, format);
+ }
+
+ return format;
+ }
+
+ public static void clearThreadLocal() {
+ THREADLOCAL_FORMATS.remove();
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/HttpClientUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/HttpClientUtils.java
new file mode 100644
index 000000000..3c7769c2a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/HttpClientUtils.java
@@ -0,0 +1,149 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.client.HttpClient;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * Convenience methods for closing response and client objects.
+ *
+ * @since 4.2
+ */
+public class HttpClientUtils {
+
+ private HttpClientUtils() {
+ }
+
+ /**
+ * Unconditionally close a response.
+ * <p>
+ * Example Code:
+ *
+ * <pre>
+ * HttpResponse httpResponse = null;
+ * try {
+ * httpResponse = httpClient.execute(httpGet);
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * HttpClientUtils.closeQuietly(httpResponse);
+ * }
+ * </pre>
+ *
+ * @param response
+ * the HttpResponse to release resources, may be null or already
+ * closed.
+ *
+ * @since 4.2
+ */
+ public static void closeQuietly(final HttpResponse response) {
+ if (response != null) {
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ try {
+ EntityUtils.consume(entity);
+ } catch (final IOException ex) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Unconditionally close a response.
+ * <p>
+ * Example Code:
+ *
+ * <pre>
+ * HttpResponse httpResponse = null;
+ * try {
+ * httpResponse = httpClient.execute(httpGet);
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * HttpClientUtils.closeQuietly(httpResponse);
+ * }
+ * </pre>
+ *
+ * @param response
+ * the HttpResponse to release resources, may be null or already
+ * closed.
+ *
+ * @since 4.3
+ */
+ public static void closeQuietly(final CloseableHttpResponse response) {
+ if (response != null) {
+ try {
+ try {
+ EntityUtils.consume(response.getEntity());
+ } finally {
+ response.close();
+ }
+ } catch (final IOException ignore) {
+ }
+ }
+ }
+
+ /**
+ * Unconditionally close a httpClient. Shuts down the underlying connection
+ * manager and releases the resources.
+ * <p>
+ * Example Code:
+ *
+ * <pre>
+ * HttpClient httpClient = HttpClients.createDefault();
+ * try {
+ * httpClient.execute(request);
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * HttpClientUtils.closeQuietly(httpClient);
+ * }
+ * </pre>
+ *
+ * @param httpClient
+ * the HttpClient to close, may be null or already closed.
+ * @since 4.2
+ */
+ public static void closeQuietly(final HttpClient httpClient) {
+ if (httpClient != null) {
+ if (httpClient instanceof Closeable) {
+ try {
+ ((Closeable) httpClient).close();
+ } catch (final IOException ignore) {
+ }
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Idn.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Idn.java
new file mode 100644
index 000000000..a2b5bd036
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Idn.java
@@ -0,0 +1,42 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+/**
+ * Abstraction of international domain name (IDN) conversion.
+ *
+ * @since 4.0
+ */
+public interface Idn {
+ /**
+ * Converts a name from its punycode representation to Unicode.
+ * The name may be a single hostname or a dot-separated qualified domain name.
+ * @param punycode the Punycode representation
+ * @return the Unicode domain name
+ */
+ String toUnicode(String punycode);
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/JdkIdn.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/JdkIdn.java
new file mode 100644
index 000000000..53d46fe23
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/JdkIdn.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Uses the java.net.IDN class through reflection.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class JdkIdn implements Idn {
+ private final Method toUnicode;
+
+ /**
+ *
+ * @throws ClassNotFoundException if java.net.IDN is not available
+ */
+ public JdkIdn() throws ClassNotFoundException {
+ final Class<?> clazz = Class.forName("java.net.IDN");
+ try {
+ toUnicode = clazz.getMethod("toUnicode", String.class);
+ } catch (final SecurityException e) {
+ // doesn't happen
+ throw new IllegalStateException(e.getMessage(), e);
+ } catch (final NoSuchMethodException e) {
+ // doesn't happen
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ }
+
+ public String toUnicode(final String punycode) {
+ try {
+ return (String) toUnicode.invoke(null, punycode);
+ } catch (final IllegalAccessException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ } catch (final InvocationTargetException e) {
+ final Throwable t = e.getCause();
+ throw new RuntimeException(t.getMessage(), t);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Punycode.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Punycode.java
new file mode 100644
index 000000000..fa4872c41
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Punycode.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Facade that provides conversion between Unicode and Punycode domain names.
+ * It will use an appropriate implementation.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class Punycode {
+ private static final Idn impl;
+ static {
+ Idn _impl;
+ try {
+ _impl = new JdkIdn();
+ } catch (final Exception e) {
+ _impl = new Rfc3492Idn();
+ }
+ impl = _impl;
+ }
+
+ public static String toUnicode(final String punycode) {
+ return impl.toUnicode(punycode);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Rfc3492Idn.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Rfc3492Idn.java
new file mode 100644
index 000000000..ccf980050
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/Rfc3492Idn.java
@@ -0,0 +1,141 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.util.StringTokenizer;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Implementation from pseudo code in RFC 3492.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class Rfc3492Idn implements Idn {
+ private static final int base = 36;
+ private static final int tmin = 1;
+ private static final int tmax = 26;
+ private static final int skew = 38;
+ private static final int damp = 700;
+ private static final int initial_bias = 72;
+ private static final int initial_n = 128;
+ private static final char delimiter = '-';
+ private static final String ACE_PREFIX = "xn--";
+
+ private int adapt(final int delta, final int numpoints, final boolean firsttime) {
+ int d = delta;
+ if (firsttime) {
+ d = d / damp;
+ } else {
+ d = d / 2;
+ }
+ d = d + (d / numpoints);
+ int k = 0;
+ while (d > ((base - tmin) * tmax) / 2) {
+ d = d / (base - tmin);
+ k = k + base;
+ }
+ return k + (((base - tmin + 1) * d) / (d + skew));
+ }
+
+ private int digit(final char c) {
+ if ((c >= 'A') && (c <= 'Z')) {
+ return (c - 'A');
+ }
+ if ((c >= 'a') && (c <= 'z')) {
+ return (c - 'a');
+ }
+ if ((c >= '0') && (c <= '9')) {
+ return (c - '0') + 26;
+ }
+ throw new IllegalArgumentException("illegal digit: "+ c);
+ }
+
+ public String toUnicode(final String punycode) {
+ final StringBuilder unicode = new StringBuilder(punycode.length());
+ final StringTokenizer tok = new StringTokenizer(punycode, ".");
+ while (tok.hasMoreTokens()) {
+ String t = tok.nextToken();
+ if (unicode.length() > 0) {
+ unicode.append('.');
+ }
+ if (t.startsWith(ACE_PREFIX)) {
+ t = decode(t.substring(4));
+ }
+ unicode.append(t);
+ }
+ return unicode.toString();
+ }
+
+ protected String decode(final String s) {
+ String input = s;
+ int n = initial_n;
+ int i = 0;
+ int bias = initial_bias;
+ final StringBuilder output = new StringBuilder(input.length());
+ final int lastdelim = input.lastIndexOf(delimiter);
+ if (lastdelim != -1) {
+ output.append(input.subSequence(0, lastdelim));
+ input = input.substring(lastdelim + 1);
+ }
+
+ while (input.length() > 0) {
+ final int oldi = i;
+ int w = 1;
+ for (int k = base;; k += base) {
+ if (input.length() == 0) {
+ break;
+ }
+ final char c = input.charAt(0);
+ input = input.substring(1);
+ final int digit = digit(c);
+ i = i + digit * w; // FIXME fail on overflow
+ final int t;
+ if (k <= bias + tmin) {
+ t = tmin;
+ } else if (k >= bias + tmax) {
+ t = tmax;
+ } else {
+ t = k - bias;
+ }
+ if (digit < t) {
+ break;
+ }
+ w = w * (base - t); // FIXME fail on overflow
+ }
+ bias = adapt(i - oldi, output.length() + 1, (oldi == 0));
+ n = n + i / (output.length() + 1); // FIXME fail on overflow
+ i = i % (output.length() + 1);
+ // {if n is a basic code point then fail}
+ output.insert(i, (char) n);
+ i++;
+ }
+ return output.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIBuilder.java
new file mode 100644
index 000000000..e41958f7f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIBuilder.java
@@ -0,0 +1,490 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.util.InetAddressUtils;
+import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
+
+/**
+ * Builder for {@link URI} instances.
+ *
+ * @since 4.2
+ */
+@NotThreadSafe
+public class URIBuilder {
+
+ private String scheme;
+ private String encodedSchemeSpecificPart;
+ private String encodedAuthority;
+ private String userInfo;
+ private String encodedUserInfo;
+ private String host;
+ private int port;
+ private String path;
+ private String encodedPath;
+ private String encodedQuery;
+ private List<NameValuePair> queryParams;
+ private String query;
+ private String fragment;
+ private String encodedFragment;
+
+ /**
+ * Constructs an empty instance.
+ */
+ public URIBuilder() {
+ super();
+ this.port = -1;
+ }
+
+ /**
+ * Construct an instance from the string which must be a valid URI.
+ *
+ * @param string a valid URI in string form
+ * @throws URISyntaxException if the input is not a valid URI
+ */
+ public URIBuilder(final String string) throws URISyntaxException {
+ super();
+ digestURI(new URI(string));
+ }
+
+ /**
+ * Construct an instance from the provided URI.
+ * @param uri
+ */
+ public URIBuilder(final URI uri) {
+ super();
+ digestURI(uri);
+ }
+
+ private List <NameValuePair> parseQuery(final String query, final Charset charset) {
+ if (query != null && query.length() > 0) {
+ return URLEncodedUtils.parse(query, charset);
+ }
+ return null;
+ }
+
+ /**
+ * Builds a {@link URI} instance.
+ */
+ public URI build() throws URISyntaxException {
+ return new URI(buildString());
+ }
+
+ private String buildString() {
+ final StringBuilder sb = new StringBuilder();
+ if (this.scheme != null) {
+ sb.append(this.scheme).append(':');
+ }
+ if (this.encodedSchemeSpecificPart != null) {
+ sb.append(this.encodedSchemeSpecificPart);
+ } else {
+ if (this.encodedAuthority != null) {
+ sb.append("//").append(this.encodedAuthority);
+ } else if (this.host != null) {
+ sb.append("//");
+ if (this.encodedUserInfo != null) {
+ sb.append(this.encodedUserInfo).append("@");
+ } else if (this.userInfo != null) {
+ sb.append(encodeUserInfo(this.userInfo)).append("@");
+ }
+ if (InetAddressUtils.isIPv6Address(this.host)) {
+ sb.append("[").append(this.host).append("]");
+ } else {
+ sb.append(this.host);
+ }
+ if (this.port >= 0) {
+ sb.append(":").append(this.port);
+ }
+ }
+ if (this.encodedPath != null) {
+ sb.append(normalizePath(this.encodedPath));
+ } else if (this.path != null) {
+ sb.append(encodePath(normalizePath(this.path)));
+ }
+ if (this.encodedQuery != null) {
+ sb.append("?").append(this.encodedQuery);
+ } else if (this.queryParams != null) {
+ sb.append("?").append(encodeUrlForm(this.queryParams));
+ } else if (this.query != null) {
+ sb.append("?").append(encodeUric(this.query));
+ }
+ }
+ if (this.encodedFragment != null) {
+ sb.append("#").append(this.encodedFragment);
+ } else if (this.fragment != null) {
+ sb.append("#").append(encodeUric(this.fragment));
+ }
+ return sb.toString();
+ }
+
+ private void digestURI(final URI uri) {
+ this.scheme = uri.getScheme();
+ this.encodedSchemeSpecificPart = uri.getRawSchemeSpecificPart();
+ this.encodedAuthority = uri.getRawAuthority();
+ this.host = uri.getHost();
+ this.port = uri.getPort();
+ this.encodedUserInfo = uri.getRawUserInfo();
+ this.userInfo = uri.getUserInfo();
+ this.encodedPath = uri.getRawPath();
+ this.path = uri.getPath();
+ this.encodedQuery = uri.getRawQuery();
+ this.queryParams = parseQuery(uri.getRawQuery(), Consts.UTF_8);
+ this.encodedFragment = uri.getRawFragment();
+ this.fragment = uri.getFragment();
+ }
+
+ private String encodeUserInfo(final String userInfo) {
+ return URLEncodedUtils.encUserInfo(userInfo, Consts.UTF_8);
+ }
+
+ private String encodePath(final String path) {
+ return URLEncodedUtils.encPath(path, Consts.UTF_8);
+ }
+
+ private String encodeUrlForm(final List<NameValuePair> params) {
+ return URLEncodedUtils.format(params, Consts.UTF_8);
+ }
+
+ private String encodeUric(final String fragment) {
+ return URLEncodedUtils.encUric(fragment, Consts.UTF_8);
+ }
+
+ /**
+ * Sets URI scheme.
+ */
+ public URIBuilder setScheme(final String scheme) {
+ this.scheme = scheme;
+ return this;
+ }
+
+ /**
+ * Sets URI user info. The value is expected to be unescaped and may contain non ASCII
+ * characters.
+ */
+ public URIBuilder setUserInfo(final String userInfo) {
+ this.userInfo = userInfo;
+ this.encodedSchemeSpecificPart = null;
+ this.encodedAuthority = null;
+ this.encodedUserInfo = null;
+ return this;
+ }
+
+ /**
+ * Sets URI user info as a combination of username and password. These values are expected to
+ * be unescaped and may contain non ASCII characters.
+ */
+ public URIBuilder setUserInfo(final String username, final String password) {
+ return setUserInfo(username + ':' + password);
+ }
+
+ /**
+ * Sets URI host.
+ */
+ public URIBuilder setHost(final String host) {
+ this.host = host;
+ this.encodedSchemeSpecificPart = null;
+ this.encodedAuthority = null;
+ return this;
+ }
+
+ /**
+ * Sets URI port.
+ */
+ public URIBuilder setPort(final int port) {
+ this.port = port < 0 ? -1 : port;
+ this.encodedSchemeSpecificPart = null;
+ this.encodedAuthority = null;
+ return this;
+ }
+
+ /**
+ * Sets URI path. The value is expected to be unescaped and may contain non ASCII characters.
+ */
+ public URIBuilder setPath(final String path) {
+ this.path = path;
+ this.encodedSchemeSpecificPart = null;
+ this.encodedPath = null;
+ return this;
+ }
+
+ /**
+ * Removes URI query.
+ */
+ public URIBuilder removeQuery() {
+ this.queryParams = null;
+ this.query = null;
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ return this;
+ }
+
+ /**
+ * Sets URI query.
+ * <p>
+ * The value is expected to be encoded form data.
+ *
+ * @deprecated (4.3) use {@link #setParameters(List)} or {@link #setParameters(NameValuePair...)}
+ *
+ * @see URLEncodedUtils#parse
+ */
+ @Deprecated
+ public URIBuilder setQuery(final String query) {
+ this.queryParams = parseQuery(query, Consts.UTF_8);
+ this.query = null;
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ return this;
+ }
+
+ /**
+ * Sets URI query parameters. The parameter name / values are expected to be unescaped
+ * and may contain non ASCII characters.
+ * <p/>
+ * Please note query parameters and custom query component are mutually exclusive. This method
+ * will remove custom query if present.
+ *
+ * @since 4.3
+ */
+ public URIBuilder setParameters(final List <NameValuePair> nvps) {
+ if (this.queryParams == null) {
+ this.queryParams = new ArrayList<NameValuePair>();
+ } else {
+ this.queryParams.clear();
+ }
+ this.queryParams.addAll(nvps);
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ this.query = null;
+ return this;
+ }
+
+ /**
+ * Adds URI query parameters. The parameter name / values are expected to be unescaped
+ * and may contain non ASCII characters.
+ * <p/>
+ * Please note query parameters and custom query component are mutually exclusive. This method
+ * will remove custom query if present.
+ *
+ * @since 4.3
+ */
+ public URIBuilder addParameters(final List <NameValuePair> nvps) {
+ if (this.queryParams == null) {
+ this.queryParams = new ArrayList<NameValuePair>();
+ }
+ this.queryParams.addAll(nvps);
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ this.query = null;
+ return this;
+ }
+
+ /**
+ * Sets URI query parameters. The parameter name / values are expected to be unescaped
+ * and may contain non ASCII characters.
+ * <p/>
+ * Please note query parameters and custom query component are mutually exclusive. This method
+ * will remove custom query if present.
+ *
+ * @since 4.3
+ */
+ public URIBuilder setParameters(final NameValuePair... nvps) {
+ if (this.queryParams == null) {
+ this.queryParams = new ArrayList<NameValuePair>();
+ } else {
+ this.queryParams.clear();
+ }
+ for (final NameValuePair nvp: nvps) {
+ this.queryParams.add(nvp);
+ }
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ this.query = null;
+ return this;
+ }
+
+ /**
+ * Adds parameter to URI query. The parameter name and value are expected to be unescaped
+ * and may contain non ASCII characters.
+ * <p/>
+ * Please note query parameters and custom query component are mutually exclusive. This method
+ * will remove custom query if present.
+ */
+ public URIBuilder addParameter(final String param, final String value) {
+ if (this.queryParams == null) {
+ this.queryParams = new ArrayList<NameValuePair>();
+ }
+ this.queryParams.add(new BasicNameValuePair(param, value));
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ this.query = null;
+ return this;
+ }
+
+ /**
+ * Sets parameter of URI query overriding existing value if set. The parameter name and value
+ * are expected to be unescaped and may contain non ASCII characters.
+ * <p/>
+ * Please note query parameters and custom query component are mutually exclusive. This method
+ * will remove custom query if present.
+ */
+ public URIBuilder setParameter(final String param, final String value) {
+ if (this.queryParams == null) {
+ this.queryParams = new ArrayList<NameValuePair>();
+ }
+ if (!this.queryParams.isEmpty()) {
+ for (final Iterator<NameValuePair> it = this.queryParams.iterator(); it.hasNext(); ) {
+ final NameValuePair nvp = it.next();
+ if (nvp.getName().equals(param)) {
+ it.remove();
+ }
+ }
+ }
+ this.queryParams.add(new BasicNameValuePair(param, value));
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ this.query = null;
+ return this;
+ }
+
+ /**
+ * Clears URI query parameters.
+ *
+ * @since 4.3
+ */
+ public URIBuilder clearParameters() {
+ this.queryParams = null;
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ return this;
+ }
+
+ /**
+ * Sets custom URI query. The value is expected to be unescaped and may contain non ASCII
+ * characters.
+ * <p/>
+ * Please note query parameters and custom query component are mutually exclusive. This method
+ * will remove query parameters if present.
+ *
+ * @since 4.3
+ */
+ public URIBuilder setCustomQuery(final String query) {
+ this.query = query;
+ this.encodedQuery = null;
+ this.encodedSchemeSpecificPart = null;
+ this.queryParams = null;
+ return this;
+ }
+
+ /**
+ * Sets URI fragment. The value is expected to be unescaped and may contain non ASCII
+ * characters.
+ */
+ public URIBuilder setFragment(final String fragment) {
+ this.fragment = fragment;
+ this.encodedFragment = null;
+ return this;
+ }
+
+ /**
+ * @since 4.3
+ */
+ public boolean isAbsolute() {
+ return this.scheme != null;
+ }
+
+ /**
+ * @since 4.3
+ */
+ public boolean isOpaque() {
+ return this.path == null;
+ }
+
+ public String getScheme() {
+ return this.scheme;
+ }
+
+ public String getUserInfo() {
+ return this.userInfo;
+ }
+
+ public String getHost() {
+ return this.host;
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ public String getPath() {
+ return this.path;
+ }
+
+ public List<NameValuePair> getQueryParams() {
+ if (this.queryParams != null) {
+ return new ArrayList<NameValuePair>(this.queryParams);
+ } else {
+ return new ArrayList<NameValuePair>();
+ }
+ }
+
+ public String getFragment() {
+ return this.fragment;
+ }
+
+ @Override
+ public String toString() {
+ return buildString();
+ }
+
+ private static String normalizePath(final String path) {
+ String s = path;
+ if (s == null) {
+ return null;
+ }
+ int n = 0;
+ for (; n < s.length(); n++) {
+ if (s.charAt(n) != '/') {
+ break;
+ }
+ }
+ if (n > 1) {
+ s = s.substring(n - 1);
+ }
+ return s;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIUtils.java
new file mode 100644
index 000000000..73619c90a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIUtils.java
@@ -0,0 +1,428 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Locale;
+import java.util.Stack;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+/**
+ * A collection of utilities for {@link URI URIs}, to workaround
+ * bugs within the class or for ease-of-use features.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class URIUtils {
+
+ /**
+ * Constructs a {@link URI} using all the parameters. This should be
+ * used instead of
+ * {@link URI#URI(String, String, String, int, String, String, String)}
+ * or any of the other URI multi-argument URI constructors.
+ *
+ * @param scheme
+ * Scheme name
+ * @param host
+ * Host name
+ * @param port
+ * Port number
+ * @param path
+ * Path
+ * @param query
+ * Query
+ * @param fragment
+ * Fragment
+ *
+ * @throws URISyntaxException
+ * If both a scheme and a path are given but the path is
+ * relative, if the URI string constructed from the given
+ * components violates RFC&nbsp;2396, or if the authority
+ * component of the string is present but cannot be parsed
+ * as a server-based authority
+ *
+ * @deprecated (4.2) use {@link URIBuilder}.
+ */
+ @Deprecated
+ public static URI createURI(
+ final String scheme,
+ final String host,
+ final int port,
+ final String path,
+ final String query,
+ final String fragment) throws URISyntaxException {
+ final StringBuilder buffer = new StringBuilder();
+ if (host != null) {
+ if (scheme != null) {
+ buffer.append(scheme);
+ buffer.append("://");
+ }
+ buffer.append(host);
+ if (port > 0) {
+ buffer.append(':');
+ buffer.append(port);
+ }
+ }
+ if (path == null || !path.startsWith("/")) {
+ buffer.append('/');
+ }
+ if (path != null) {
+ buffer.append(path);
+ }
+ if (query != null) {
+ buffer.append('?');
+ buffer.append(query);
+ }
+ if (fragment != null) {
+ buffer.append('#');
+ buffer.append(fragment);
+ }
+ return new URI(buffer.toString());
+ }
+
+ /**
+ * A convenience method for creating a new {@link URI} whose scheme, host
+ * and port are taken from the target host, but whose path, query and
+ * fragment are taken from the existing URI. The fragment is only used if
+ * dropFragment is false. The path is set to "/" if not explicitly specified.
+ *
+ * @param uri
+ * Contains the path, query and fragment to use.
+ * @param target
+ * Contains the scheme, host and port to use.
+ * @param dropFragment
+ * True if the fragment should not be copied.
+ *
+ * @throws URISyntaxException
+ * If the resulting URI is invalid.
+ */
+ public static URI rewriteURI(
+ final URI uri,
+ final HttpHost target,
+ final boolean dropFragment) throws URISyntaxException {
+ Args.notNull(uri, "URI");
+ if (uri.isOpaque()) {
+ return uri;
+ }
+ final URIBuilder uribuilder = new URIBuilder(uri);
+ if (target != null) {
+ uribuilder.setScheme(target.getSchemeName());
+ uribuilder.setHost(target.getHostName());
+ uribuilder.setPort(target.getPort());
+ } else {
+ uribuilder.setScheme(null);
+ uribuilder.setHost(null);
+ uribuilder.setPort(-1);
+ }
+ if (dropFragment) {
+ uribuilder.setFragment(null);
+ }
+ if (TextUtils.isEmpty(uribuilder.getPath())) {
+ uribuilder.setPath("/");
+ }
+ return uribuilder.build();
+ }
+
+ /**
+ * A convenience method for
+ * {@link URIUtils#rewriteURI(URI, HttpHost, boolean)} that always keeps the
+ * fragment.
+ */
+ public static URI rewriteURI(
+ final URI uri,
+ final HttpHost target) throws URISyntaxException {
+ return rewriteURI(uri, target, false);
+ }
+
+ /**
+ * A convenience method that creates a new {@link URI} whose scheme, host, port, path,
+ * query are taken from the existing URI, dropping any fragment or user-information.
+ * The path is set to "/" if not explicitly specified. The existing URI is returned
+ * unmodified if it has no fragment or user-information and has a path.
+ *
+ * @param uri
+ * original URI.
+ * @throws URISyntaxException
+ * If the resulting URI is invalid.
+ */
+ public static URI rewriteURI(final URI uri) throws URISyntaxException {
+ Args.notNull(uri, "URI");
+ if (uri.isOpaque()) {
+ return uri;
+ }
+ final URIBuilder uribuilder = new URIBuilder(uri);
+ if (uribuilder.getUserInfo() != null) {
+ uribuilder.setUserInfo(null);
+ }
+ if (TextUtils.isEmpty(uribuilder.getPath())) {
+ uribuilder.setPath("/");
+ }
+ if (uribuilder.getHost() != null) {
+ uribuilder.setHost(uribuilder.getHost().toLowerCase(Locale.ENGLISH));
+ }
+ uribuilder.setFragment(null);
+ return uribuilder.build();
+ }
+
+ /**
+ * Resolves a URI reference against a base URI. Work-around for bug in
+ * java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
+ *
+ * @param baseURI the base URI
+ * @param reference the URI reference
+ * @return the resulting URI
+ */
+ public static URI resolve(final URI baseURI, final String reference) {
+ return URIUtils.resolve(baseURI, URI.create(reference));
+ }
+
+ /**
+ * Resolves a URI reference against a base URI. Work-around for bugs in
+ * java.net.URI (e.g. <http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
+ *
+ * @param baseURI the base URI
+ * @param reference the URI reference
+ * @return the resulting URI
+ */
+ public static URI resolve(final URI baseURI, final URI reference){
+ Args.notNull(baseURI, "Base URI");
+ Args.notNull(reference, "Reference URI");
+ URI ref = reference;
+ final String s = ref.toString();
+ if (s.startsWith("?")) {
+ return resolveReferenceStartingWithQueryString(baseURI, ref);
+ }
+ final boolean emptyReference = s.length() == 0;
+ if (emptyReference) {
+ ref = URI.create("#");
+ }
+ URI resolved = baseURI.resolve(ref);
+ if (emptyReference) {
+ final String resolvedString = resolved.toString();
+ resolved = URI.create(resolvedString.substring(0,
+ resolvedString.indexOf('#')));
+ }
+ return normalizeSyntax(resolved);
+ }
+
+ /**
+ * Resolves a reference starting with a query string.
+ *
+ * @param baseURI the base URI
+ * @param reference the URI reference starting with a query string
+ * @return the resulting URI
+ */
+ private static URI resolveReferenceStartingWithQueryString(
+ final URI baseURI, final URI reference) {
+ String baseUri = baseURI.toString();
+ baseUri = baseUri.indexOf('?') > -1 ?
+ baseUri.substring(0, baseUri.indexOf('?')) : baseUri;
+ return URI.create(baseUri + reference.toString());
+ }
+
+ /**
+ * Removes dot segments according to RFC 3986, section 5.2.4 and
+ * Syntax-Based Normalization according to RFC 3986, section 6.2.2.
+ *
+ * @param uri the original URI
+ * @return the URI without dot segments
+ */
+ private static URI normalizeSyntax(final URI uri) {
+ if (uri.isOpaque() || uri.getAuthority() == null) {
+ // opaque and file: URIs
+ return uri;
+ }
+ Args.check(uri.isAbsolute(), "Base URI must be absolute");
+ final String path = uri.getPath() == null ? "" : uri.getPath();
+ final String[] inputSegments = path.split("/");
+ final Stack<String> outputSegments = new Stack<String>();
+ for (final String inputSegment : inputSegments) {
+ if ((inputSegment.length() == 0)
+ || (".".equals(inputSegment))) {
+ // Do nothing
+ } else if ("..".equals(inputSegment)) {
+ if (!outputSegments.isEmpty()) {
+ outputSegments.pop();
+ }
+ } else {
+ outputSegments.push(inputSegment);
+ }
+ }
+ final StringBuilder outputBuffer = new StringBuilder();
+ for (final String outputSegment : outputSegments) {
+ outputBuffer.append('/').append(outputSegment);
+ }
+ if (path.lastIndexOf('/') == path.length() - 1) {
+ // path.endsWith("/") || path.equals("")
+ outputBuffer.append('/');
+ }
+ try {
+ final String scheme = uri.getScheme().toLowerCase(Locale.ENGLISH);
+ final String auth = uri.getAuthority().toLowerCase(Locale.ENGLISH);
+ final URI ref = new URI(scheme, auth, outputBuffer.toString(),
+ null, null);
+ if (uri.getQuery() == null && uri.getFragment() == null) {
+ return ref;
+ }
+ final StringBuilder normalized = new StringBuilder(
+ ref.toASCIIString());
+ if (uri.getQuery() != null) {
+ // query string passed through unchanged
+ normalized.append('?').append(uri.getRawQuery());
+ }
+ if (uri.getFragment() != null) {
+ // fragment passed through unchanged
+ normalized.append('#').append(uri.getRawFragment());
+ }
+ return URI.create(normalized.toString());
+ } catch (final URISyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Extracts target host from the given {@link URI}.
+ *
+ * @param uri
+ * @return the target host if the URI is absolute or <code>null</null> if the URI is
+ * relative or does not contain a valid host name.
+ *
+ * @since 4.1
+ */
+ public static HttpHost extractHost(final URI uri) {
+ if (uri == null) {
+ return null;
+ }
+ HttpHost target = null;
+ if (uri.isAbsolute()) {
+ int port = uri.getPort(); // may be overridden later
+ String host = uri.getHost();
+ if (host == null) { // normal parse failed; let's do it ourselves
+ // authority does not seem to care about the valid character-set for host names
+ host = uri.getAuthority();
+ if (host != null) {
+ // Strip off any leading user credentials
+ final int at = host.indexOf('@');
+ if (at >= 0) {
+ if (host.length() > at+1 ) {
+ host = host.substring(at+1);
+ } else {
+ host = null; // @ on its own
+ }
+ }
+ // Extract the port suffix, if present
+ if (host != null) {
+ final int colon = host.indexOf(':');
+ if (colon >= 0) {
+ final int pos = colon + 1;
+ int len = 0;
+ for (int i = pos; i < host.length(); i++) {
+ if (Character.isDigit(host.charAt(i))) {
+ len++;
+ } else {
+ break;
+ }
+ }
+ if (len > 0) {
+ try {
+ port = Integer.parseInt(host.substring(pos, pos + len));
+ } catch (final NumberFormatException ex) {
+ }
+ }
+ host = host.substring(0, colon);
+ }
+ }
+ }
+ }
+ final String scheme = uri.getScheme();
+ if (!TextUtils.isBlank(host)) {
+ target = new HttpHost(host, port, scheme);
+ }
+ }
+ return target;
+ }
+
+ /**
+ * Derives the interpreted (absolute) URI that was used to generate the last
+ * request. This is done by extracting the request-uri and target origin for
+ * the last request and scanning all the redirect locations for the last
+ * fragment identifier, then combining the result into a {@link URI}.
+ *
+ * @param originalURI
+ * original request before any redirects
+ * @param target
+ * if the last URI is relative, it is resolved against this target,
+ * or <code>null</code> if not available.
+ * @param redirects
+ * collection of redirect locations since the original request
+ * or <code>null</code> if not available.
+ * @return interpreted (absolute) URI
+ */
+ public static URI resolve(
+ final URI originalURI,
+ final HttpHost target,
+ final List<URI> redirects) throws URISyntaxException {
+ Args.notNull(originalURI, "Request URI");
+ final URIBuilder uribuilder;
+ if (redirects == null || redirects.isEmpty()) {
+ uribuilder = new URIBuilder(originalURI);
+ } else {
+ uribuilder = new URIBuilder(redirects.get(redirects.size() - 1));
+ String frag = uribuilder.getFragment();
+ // read interpreted fragment identifier from redirect locations
+ for (int i = redirects.size() - 1; frag == null && i >= 0; i--) {
+ frag = redirects.get(i).getFragment();
+ }
+ uribuilder.setFragment(frag);
+ }
+ // read interpreted fragment identifier from original request
+ if (uribuilder.getFragment() == null) {
+ uribuilder.setFragment(originalURI.getFragment());
+ }
+ // last target origin
+ if (target != null && !uribuilder.isAbsolute()) {
+ uribuilder.setScheme(target.getSchemeName());
+ uribuilder.setHost(target.getHostName());
+ uribuilder.setPort(target.getPort());
+ }
+ return uribuilder.build();
+ }
+
+ /**
+ * This class should not be instantiated.
+ */
+ private URIUtils() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URLEncodedUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URLEncodedUtils.java
new file mode 100644
index 000000000..97465401f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URLEncodedUtils.java
@@ -0,0 +1,628 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.client.utils;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.List;
+import java.util.Scanner;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.message.BasicHeaderValueParser;
+import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * A collection of utilities for encoding URLs.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class URLEncodedUtils {
+
+ /**
+ * The default HTML form content type.
+ */
+ public static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
+
+ private static final char QP_SEP_A = '&';
+ private static final char QP_SEP_S = ';';
+ private static final String NAME_VALUE_SEPARATOR = "=";
+
+ /**
+ * Returns a list of {@link NameValuePair NameValuePairs} as built from the URI's query portion. For example, a URI
+ * of http://example.org/path/to/file?a=1&b=2&c=3 would return a list of three NameValuePairs, one for a=1, one for
+ * b=2, and one for c=3. By convention, {@code '&'} and {@code ';'} are accepted as parameter separators.
+ * <p>
+ * This is typically useful while parsing an HTTP PUT.
+ *
+ * This API is currently only used for testing.
+ *
+ * @param uri
+ * URI to parse
+ * @param charset
+ * Charset name to use while parsing the query
+ * @return a list of {@link NameValuePair} as built from the URI's query portion.
+ */
+ public static List <NameValuePair> parse(final URI uri, final String charset) {
+ final String query = uri.getRawQuery();
+ if (query != null && query.length() > 0) {
+ final List<NameValuePair> result = new ArrayList<NameValuePair>();
+ final Scanner scanner = new Scanner(query);
+ parse(result, scanner, QP_SEP_PATTERN, charset);
+ return result;
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * Returns a list of {@link NameValuePair NameValuePairs} as parsed from an {@link HttpEntity}. The encoding is
+ * taken from the entity's Content-Encoding header.
+ * <p>
+ * This is typically used while parsing an HTTP POST.
+ *
+ * @param entity
+ * The entity to parse
+ * @return a list of {@link NameValuePair} as built from the URI's query portion.
+ * @throws IOException
+ * If there was an exception getting the entity's data.
+ */
+ public static List <NameValuePair> parse(
+ final HttpEntity entity) throws IOException {
+ final ContentType contentType = ContentType.get(entity);
+ if (contentType != null && contentType.getMimeType().equalsIgnoreCase(CONTENT_TYPE)) {
+ final String content = EntityUtils.toString(entity, Consts.ASCII);
+ if (content != null && content.length() > 0) {
+ Charset charset = contentType.getCharset();
+ if (charset == null) {
+ charset = HTTP.DEF_CONTENT_CHARSET;
+ }
+ return parse(content, charset, QP_SEPS);
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * Returns true if the entity's Content-Type header is
+ * <code>application/x-www-form-urlencoded</code>.
+ */
+ public static boolean isEncoded(final HttpEntity entity) {
+ final Header h = entity.getContentType();
+ if (h != null) {
+ final HeaderElement[] elems = h.getElements();
+ if (elems.length > 0) {
+ final String contentType = elems[0].getName();
+ return contentType.equalsIgnoreCase(CONTENT_TYPE);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds all parameters within the Scanner to the list of <code>parameters</code>, as encoded by
+ * <code>encoding</code>. For example, a scanner containing the string <code>a=1&b=2&c=3</code> would add the
+ * {@link NameValuePair NameValuePairs} a=1, b=2, and c=3 to the list of parameters. By convention, {@code '&'} and
+ * {@code ';'} are accepted as parameter separators.
+ *
+ * @param parameters
+ * List to add parameters to.
+ * @param scanner
+ * Input that contains the parameters to parse.
+ * @param charset
+ * Encoding to use when decoding the parameters.
+ */
+ public static void parse(
+ final List <NameValuePair> parameters,
+ final Scanner scanner,
+ final String charset) {
+ parse(parameters, scanner, QP_SEP_PATTERN, charset);
+ }
+
+ /**
+ * Adds all parameters within the Scanner to the list of
+ * <code>parameters</code>, as encoded by <code>encoding</code>. For
+ * example, a scanner containing the string <code>a=1&b=2&c=3</code> would
+ * add the {@link NameValuePair NameValuePairs} a=1, b=2, and c=3 to the
+ * list of parameters.
+ *
+ * @param parameters
+ * List to add parameters to.
+ * @param scanner
+ * Input that contains the parameters to parse.
+ * @param parameterSepartorPattern
+ * The Pattern string for parameter separators, by convention {@code "[&;]"}
+ * @param charset
+ * Encoding to use when decoding the parameters.
+ */
+ public static void parse(
+ final List <NameValuePair> parameters,
+ final Scanner scanner,
+ final String parameterSepartorPattern,
+ final String charset) {
+ scanner.useDelimiter(parameterSepartorPattern);
+ while (scanner.hasNext()) {
+ String name = null;
+ String value = null;
+ final String token = scanner.next();
+ final int i = token.indexOf(NAME_VALUE_SEPARATOR);
+ if (i != -1) {
+ name = decodeFormFields(token.substring(0, i).trim(), charset);
+ value = decodeFormFields(token.substring(i + 1).trim(), charset);
+ } else {
+ name = decodeFormFields(token.trim(), charset);
+ }
+ parameters.add(new BasicNameValuePair(name, value));
+ }
+ }
+
+ /**
+ * Query parameter separators.
+ */
+ private static final char[] QP_SEPS = new char[] { QP_SEP_A, QP_SEP_S };
+
+ /**
+ * Query parameter separator pattern.
+ */
+ private static final String QP_SEP_PATTERN = "[" + new String(QP_SEPS) + "]";
+
+ /**
+ * Returns a list of {@link NameValuePair NameValuePairs} as parsed from the given string using the given character
+ * encoding. By convention, {@code '&'} and {@code ';'} are accepted as parameter separators.
+ *
+ * @param s
+ * text to parse.
+ * @param charset
+ * Encoding to use when decoding the parameters.
+ * @return a list of {@link NameValuePair} as built from the URI's query portion.
+ *
+ * @since 4.2
+ */
+ public static List<NameValuePair> parse(final String s, final Charset charset) {
+ return parse(s, charset, QP_SEPS);
+ }
+
+ /**
+ * Returns a list of {@link NameValuePair NameValuePairs} as parsed from the given string using the given character
+ * encoding.
+ *
+ * @param s
+ * text to parse.
+ * @param charset
+ * Encoding to use when decoding the parameters.
+ * @param parameterSeparator
+ * The characters used to separate parameters, by convention, {@code '&'} and {@code ';'}.
+ * @return a list of {@link NameValuePair} as built from the URI's query portion.
+ *
+ * @since 4.3
+ */
+ public static List<NameValuePair> parse(final String s, final Charset charset, final char... parameterSeparator) {
+ if (s == null) {
+ return Collections.emptyList();
+ }
+ final BasicHeaderValueParser parser = BasicHeaderValueParser.INSTANCE;
+ final CharArrayBuffer buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ final ParserCursor cursor = new ParserCursor(0, buffer.length());
+ final List<NameValuePair> list = new ArrayList<NameValuePair>();
+ while (!cursor.atEnd()) {
+ final NameValuePair nvp = parser.parseNameValuePair(buffer, cursor, parameterSeparator);
+ if (nvp.getName().length() > 0) {
+ list.add(new BasicNameValuePair(
+ decodeFormFields(nvp.getName(), charset),
+ decodeFormFields(nvp.getValue(), charset)));
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns a String that is suitable for use as an {@code application/x-www-form-urlencoded}
+ * list of parameters in an HTTP PUT or HTTP POST.
+ *
+ * @param parameters The parameters to include.
+ * @param charset The encoding to use.
+ * @return An {@code application/x-www-form-urlencoded} string
+ */
+ public static String format(
+ final List <? extends NameValuePair> parameters,
+ final String charset) {
+ return format(parameters, QP_SEP_A, charset);
+ }
+
+ /**
+ * Returns a String that is suitable for use as an {@code application/x-www-form-urlencoded}
+ * list of parameters in an HTTP PUT or HTTP POST.
+ *
+ * @param parameters The parameters to include.
+ * @param parameterSeparator The parameter separator, by convention, {@code '&'} or {@code ';'}.
+ * @param charset The encoding to use.
+ * @return An {@code application/x-www-form-urlencoded} string
+ *
+ * @since 4.3
+ */
+ public static String format(
+ final List <? extends NameValuePair> parameters,
+ final char parameterSeparator,
+ final String charset) {
+ final StringBuilder result = new StringBuilder();
+ for (final NameValuePair parameter : parameters) {
+ final String encodedName = encodeFormFields(parameter.getName(), charset);
+ final String encodedValue = encodeFormFields(parameter.getValue(), charset);
+ if (result.length() > 0) {
+ result.append(parameterSeparator);
+ }
+ result.append(encodedName);
+ if (encodedValue != null) {
+ result.append(NAME_VALUE_SEPARATOR);
+ result.append(encodedValue);
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns a String that is suitable for use as an {@code application/x-www-form-urlencoded}
+ * list of parameters in an HTTP PUT or HTTP POST.
+ *
+ * @param parameters The parameters to include.
+ * @param charset The encoding to use.
+ * @return An {@code application/x-www-form-urlencoded} string
+ *
+ * @since 4.2
+ */
+ public static String format(
+ final Iterable<? extends NameValuePair> parameters,
+ final Charset charset) {
+ return format(parameters, QP_SEP_A, charset);
+ }
+
+ /**
+ * Returns a String that is suitable for use as an {@code application/x-www-form-urlencoded}
+ * list of parameters in an HTTP PUT or HTTP POST.
+ *
+ * @param parameters The parameters to include.
+ * @param parameterSeparator The parameter separator, by convention, {@code '&'} or {@code ';'}.
+ * @param charset The encoding to use.
+ * @return An {@code application/x-www-form-urlencoded} string
+ *
+ * @since 4.3
+ */
+ public static String format(
+ final Iterable<? extends NameValuePair> parameters,
+ final char parameterSeparator,
+ final Charset charset) {
+ final StringBuilder result = new StringBuilder();
+ for (final NameValuePair parameter : parameters) {
+ final String encodedName = encodeFormFields(parameter.getName(), charset);
+ final String encodedValue = encodeFormFields(parameter.getValue(), charset);
+ if (result.length() > 0) {
+ result.append(parameterSeparator);
+ }
+ result.append(encodedName);
+ if (encodedValue != null) {
+ result.append(NAME_VALUE_SEPARATOR);
+ result.append(encodedValue);
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Unreserved characters, i.e. alphanumeric, plus: {@code _ - ! . ~ ' ( ) *}
+ * <p>
+ * This list is the same as the {@code unreserved} list in
+ * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>
+ */
+ private static final BitSet UNRESERVED = new BitSet(256);
+ /**
+ * Punctuation characters: , ; : $ & + =
+ * <p>
+ * These are the additional characters allowed by userinfo.
+ */
+ private static final BitSet PUNCT = new BitSet(256);
+ /** Characters which are safe to use in userinfo,
+ * i.e. {@link #UNRESERVED} plus {@link #PUNCT}uation */
+ private static final BitSet USERINFO = new BitSet(256);
+ /** Characters which are safe to use in a path,
+ * i.e. {@link #UNRESERVED} plus {@link #PUNCT}uation plus / @ */
+ private static final BitSet PATHSAFE = new BitSet(256);
+ /** Characters which are safe to use in a query or a fragment,
+ * i.e. {@link #RESERVED} plus {@link #UNRESERVED} */
+ private static final BitSet URIC = new BitSet(256);
+
+ /**
+ * Reserved characters, i.e. {@code ;/?:@&=+$,[]}
+ * <p>
+ * This list is the same as the {@code reserved} list in
+ * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>
+ * as augmented by
+ * <a href="http://www.ietf.org/rfc/rfc2732.txt">RFC 2732</a>
+ */
+ private static final BitSet RESERVED = new BitSet(256);
+
+
+ /**
+ * Safe characters for x-www-form-urlencoded data, as per java.net.URLEncoder and browser behaviour,
+ * i.e. alphanumeric plus {@code "-", "_", ".", "*"}
+ */
+ private static final BitSet URLENCODER = new BitSet(256);
+
+ static {
+ // unreserved chars
+ // alpha characters
+ for (int i = 'a'; i <= 'z'; i++) {
+ UNRESERVED.set(i);
+ }
+ for (int i = 'A'; i <= 'Z'; i++) {
+ UNRESERVED.set(i);
+ }
+ // numeric characters
+ for (int i = '0'; i <= '9'; i++) {
+ UNRESERVED.set(i);
+ }
+ UNRESERVED.set('_'); // these are the charactes of the "mark" list
+ UNRESERVED.set('-');
+ UNRESERVED.set('.');
+ UNRESERVED.set('*');
+ URLENCODER.or(UNRESERVED); // skip remaining unreserved characters
+ UNRESERVED.set('!');
+ UNRESERVED.set('~');
+ UNRESERVED.set('\'');
+ UNRESERVED.set('(');
+ UNRESERVED.set(')');
+ // punct chars
+ PUNCT.set(',');
+ PUNCT.set(';');
+ PUNCT.set(':');
+ PUNCT.set('$');
+ PUNCT.set('&');
+ PUNCT.set('+');
+ PUNCT.set('=');
+ // Safe for userinfo
+ USERINFO.or(UNRESERVED);
+ USERINFO.or(PUNCT);
+
+ // URL path safe
+ PATHSAFE.or(UNRESERVED);
+ PATHSAFE.set('/'); // segment separator
+ PATHSAFE.set(';'); // param separator
+ PATHSAFE.set(':'); // rest as per list in 2396, i.e. : @ & = + $ ,
+ PATHSAFE.set('@');
+ PATHSAFE.set('&');
+ PATHSAFE.set('=');
+ PATHSAFE.set('+');
+ PATHSAFE.set('$');
+ PATHSAFE.set(',');
+
+ RESERVED.set(';');
+ RESERVED.set('/');
+ RESERVED.set('?');
+ RESERVED.set(':');
+ RESERVED.set('@');
+ RESERVED.set('&');
+ RESERVED.set('=');
+ RESERVED.set('+');
+ RESERVED.set('$');
+ RESERVED.set(',');
+ RESERVED.set('['); // added by RFC 2732
+ RESERVED.set(']'); // added by RFC 2732
+
+ URIC.or(RESERVED);
+ URIC.or(UNRESERVED);
+ }
+
+ private static final int RADIX = 16;
+
+ private static String urlEncode(
+ final String content,
+ final Charset charset,
+ final BitSet safechars,
+ final boolean blankAsPlus) {
+ if (content == null) {
+ return null;
+ }
+ final StringBuilder buf = new StringBuilder();
+ final ByteBuffer bb = charset.encode(content);
+ while (bb.hasRemaining()) {
+ final int b = bb.get() & 0xff;
+ if (safechars.get(b)) {
+ buf.append((char) b);
+ } else if (blankAsPlus && b == ' ') {
+ buf.append('+');
+ } else {
+ buf.append("%");
+ final char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, RADIX));
+ final char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, RADIX));
+ buf.append(hex1);
+ buf.append(hex2);
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Decode/unescape a portion of a URL, to use with the query part ensure {@code plusAsBlank} is true.
+ *
+ * @param content the portion to decode
+ * @param charset the charset to use
+ * @param plusAsBlank if {@code true}, then convert '+' to space (e.g. for www-url-form-encoded content), otherwise leave as is.
+ * @return encoded string
+ */
+ private static String urlDecode(
+ final String content,
+ final Charset charset,
+ final boolean plusAsBlank) {
+ if (content == null) {
+ return null;
+ }
+ final ByteBuffer bb = ByteBuffer.allocate(content.length());
+ final CharBuffer cb = CharBuffer.wrap(content);
+ while (cb.hasRemaining()) {
+ final char c = cb.get();
+ if (c == '%' && cb.remaining() >= 2) {
+ final char uc = cb.get();
+ final char lc = cb.get();
+ final int u = Character.digit(uc, 16);
+ final int l = Character.digit(lc, 16);
+ if (u != -1 && l != -1) {
+ bb.put((byte) ((u << 4) + l));
+ } else {
+ bb.put((byte) '%');
+ bb.put((byte) uc);
+ bb.put((byte) lc);
+ }
+ } else if (plusAsBlank && c == '+') {
+ bb.put((byte) ' ');
+ } else {
+ bb.put((byte) c);
+ }
+ }
+ bb.flip();
+ return charset.decode(bb).toString();
+ }
+
+ /**
+ * Decode/unescape www-url-form-encoded content.
+ *
+ * @param content the content to decode, will decode '+' as space
+ * @param charset the charset to use
+ * @return encoded string
+ */
+ private static String decodeFormFields (final String content, final String charset) {
+ if (content == null) {
+ return null;
+ }
+ return urlDecode(content, charset != null ? Charset.forName(charset) : Consts.UTF_8, true);
+ }
+
+ /**
+ * Decode/unescape www-url-form-encoded content.
+ *
+ * @param content the content to decode, will decode '+' as space
+ * @param charset the charset to use
+ * @return encoded string
+ */
+ private static String decodeFormFields (final String content, final Charset charset) {
+ if (content == null) {
+ return null;
+ }
+ return urlDecode(content, charset != null ? charset : Consts.UTF_8, true);
+ }
+
+ /**
+ * Encode/escape www-url-form-encoded content.
+ * <p>
+ * Uses the {@link #URLENCODER} set of characters, rather than
+ * the {@link #UNRSERVED} set; this is for compatibilty with previous
+ * releases, URLEncoder.encode() and most browsers.
+ *
+ * @param content the content to encode, will convert space to '+'
+ * @param charset the charset to use
+ * @return encoded string
+ */
+ private static String encodeFormFields(final String content, final String charset) {
+ if (content == null) {
+ return null;
+ }
+ return urlEncode(content, charset != null ? Charset.forName(charset) : Consts.UTF_8, URLENCODER, true);
+ }
+
+ /**
+ * Encode/escape www-url-form-encoded content.
+ * <p>
+ * Uses the {@link #URLENCODER} set of characters, rather than
+ * the {@link #UNRSERVED} set; this is for compatibilty with previous
+ * releases, URLEncoder.encode() and most browsers.
+ *
+ * @param content the content to encode, will convert space to '+'
+ * @param charset the charset to use
+ * @return encoded string
+ */
+ private static String encodeFormFields (final String content, final Charset charset) {
+ if (content == null) {
+ return null;
+ }
+ return urlEncode(content, charset != null ? charset : Consts.UTF_8, URLENCODER, true);
+ }
+
+ /**
+ * Encode a String using the {@link #USERINFO} set of characters.
+ * <p>
+ * Used by URIBuilder to encode the userinfo segment.
+ *
+ * @param content the string to encode, does not convert space to '+'
+ * @param charset the charset to use
+ * @return the encoded string
+ */
+ static String encUserInfo(final String content, final Charset charset) {
+ return urlEncode(content, charset, USERINFO, false);
+ }
+
+ /**
+ * Encode a String using the {@link #URIC} set of characters.
+ * <p>
+ * Used by URIBuilder to encode the query and fragment segments.
+ *
+ * @param content the string to encode, does not convert space to '+'
+ * @param charset the charset to use
+ * @return the encoded string
+ */
+ static String encUric(final String content, final Charset charset) {
+ return urlEncode(content, charset, URIC, false);
+ }
+
+ /**
+ * Encode a String using the {@link #PATHSAFE} set of characters.
+ * <p>
+ * Used by URIBuilder to encode path segments.
+ *
+ * @param content the string to encode, does not convert space to '+'
+ * @param charset the charset to use
+ * @return the encoded string
+ */
+ static String encPath(final String content, final Charset charset) {
+ return urlEncode(content, charset, PATHSAFE, false);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/package-info.java
new file mode 100644
index 000000000..7f5671654
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client utility classes.
+ */
+package ch.boye.httpclientandroidlib.client.utils;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/BasicFuture.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/BasicFuture.java
new file mode 100644
index 000000000..a2215ceca
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/BasicFuture.java
@@ -0,0 +1,154 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.concurrent;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Basic implementation of the {@link Future} interface. <tt>BasicFuture<tt>
+ * can be put into a completed state by invoking any of the following methods:
+ * {@link #cancel()}, {@link #failed(Exception)}, or {@link #completed(Object)}.
+ *
+ * @param <T> the future result type of an asynchronous operation.
+ * @since 4.2
+ */
+public class BasicFuture<T> implements Future<T>, Cancellable {
+
+ private final FutureCallback<T> callback;
+
+ private volatile boolean completed;
+ private volatile boolean cancelled;
+ private volatile T result;
+ private volatile Exception ex;
+
+ public BasicFuture(final FutureCallback<T> callback) {
+ super();
+ this.callback = callback;
+ }
+
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ public boolean isDone() {
+ return this.completed;
+ }
+
+ private T getResult() throws ExecutionException {
+ if (this.ex != null) {
+ throw new ExecutionException(this.ex);
+ }
+ return this.result;
+ }
+
+ public synchronized T get() throws InterruptedException, ExecutionException {
+ while (!this.completed) {
+ wait();
+ }
+ return getResult();
+ }
+
+ public synchronized T get(final long timeout, final TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ Args.notNull(unit, "Time unit");
+ final long msecs = unit.toMillis(timeout);
+ final long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis();
+ long waitTime = msecs;
+ if (this.completed) {
+ return getResult();
+ } else if (waitTime <= 0) {
+ throw new TimeoutException();
+ } else {
+ for (;;) {
+ wait(waitTime);
+ if (this.completed) {
+ return getResult();
+ } else {
+ waitTime = msecs - (System.currentTimeMillis() - startTime);
+ if (waitTime <= 0) {
+ throw new TimeoutException();
+ }
+ }
+ }
+ }
+ }
+
+ public boolean completed(final T result) {
+ synchronized(this) {
+ if (this.completed) {
+ return false;
+ }
+ this.completed = true;
+ this.result = result;
+ notifyAll();
+ }
+ if (this.callback != null) {
+ this.callback.completed(result);
+ }
+ return true;
+ }
+
+ public boolean failed(final Exception exception) {
+ synchronized(this) {
+ if (this.completed) {
+ return false;
+ }
+ this.completed = true;
+ this.ex = exception;
+ notifyAll();
+ }
+ if (this.callback != null) {
+ this.callback.failed(exception);
+ }
+ return true;
+ }
+
+ public boolean cancel(final boolean mayInterruptIfRunning) {
+ synchronized(this) {
+ if (this.completed) {
+ return false;
+ }
+ this.completed = true;
+ this.cancelled = true;
+ notifyAll();
+ }
+ if (this.callback != null) {
+ this.callback.cancelled();
+ }
+ return true;
+ }
+
+ public boolean cancel() {
+ return cancel(true);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/Cancellable.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/Cancellable.java
new file mode 100644
index 000000000..c51daa27f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/Cancellable.java
@@ -0,0 +1,39 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.concurrent;
+
+/**
+ * A <tt>Cancellable</tt> represents a process or an operation that can be
+ * canceled.
+ *
+ * @since 4.2
+ */
+public interface Cancellable {
+
+ boolean cancel();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/FutureCallback.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/FutureCallback.java
new file mode 100644
index 000000000..91ed93940
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/FutureCallback.java
@@ -0,0 +1,44 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.concurrent;
+
+/**
+ * A callback interface that gets invoked upon completion of
+ * a {@link java.util.concurrent.Future}.
+ *
+ * @param <T> the future result type returned by this callback.
+ * @since 4.2
+ */
+public interface FutureCallback<T> {
+
+ void completed(T result);
+
+ void failed(Exception ex);
+
+ void cancelled();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/package-info.java
new file mode 100644
index 000000000..38d2699ed
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/concurrent/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Core concurrency APIs.
+ */
+package ch.boye.httpclientandroidlib.concurrent;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/ConnectionConfig.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/ConnectionConfig.java
new file mode 100644
index 000000000..50fb21460
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/ConnectionConfig.java
@@ -0,0 +1,192 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.config;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CodingErrorAction;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * HTTP connection configuration.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class ConnectionConfig implements Cloneable {
+
+ public static final ConnectionConfig DEFAULT = new Builder().build();
+
+ private final int bufferSize;
+ private final int fragmentSizeHint;
+ private final Charset charset;
+ private final CodingErrorAction malformedInputAction;
+ private final CodingErrorAction unmappableInputAction;
+ private final MessageConstraints messageConstraints;
+
+ ConnectionConfig(
+ final int bufferSize,
+ final int fragmentSizeHint,
+ final Charset charset,
+ final CodingErrorAction malformedInputAction,
+ final CodingErrorAction unmappableInputAction,
+ final MessageConstraints messageConstraints) {
+ super();
+ this.bufferSize = bufferSize;
+ this.fragmentSizeHint = fragmentSizeHint;
+ this.charset = charset;
+ this.malformedInputAction = malformedInputAction;
+ this.unmappableInputAction = unmappableInputAction;
+ this.messageConstraints = messageConstraints;
+ }
+
+ public int getBufferSize() {
+ return bufferSize;
+ }
+
+ public int getFragmentSizeHint() {
+ return fragmentSizeHint;
+ }
+
+ public Charset getCharset() {
+ return charset;
+ }
+
+ public CodingErrorAction getMalformedInputAction() {
+ return malformedInputAction;
+ }
+
+ public CodingErrorAction getUnmappableInputAction() {
+ return unmappableInputAction;
+ }
+
+ public MessageConstraints getMessageConstraints() {
+ return messageConstraints;
+ }
+
+ @Override
+ protected ConnectionConfig clone() throws CloneNotSupportedException {
+ return (ConnectionConfig) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[bufferSize=").append(this.bufferSize)
+ .append(", fragmentSizeHint=").append(this.fragmentSizeHint)
+ .append(", charset=").append(this.charset)
+ .append(", malformedInputAction=").append(this.malformedInputAction)
+ .append(", unmappableInputAction=").append(this.unmappableInputAction)
+ .append(", messageConstraints=").append(this.messageConstraints)
+ .append("]");
+ return builder.toString();
+ }
+
+ public static ConnectionConfig.Builder custom() {
+ return new Builder();
+ }
+
+ public static ConnectionConfig.Builder copy(final ConnectionConfig config) {
+ Args.notNull(config, "Connection config");
+ return new Builder()
+ .setCharset(config.getCharset())
+ .setMalformedInputAction(config.getMalformedInputAction())
+ .setUnmappableInputAction(config.getUnmappableInputAction())
+ .setMessageConstraints(config.getMessageConstraints());
+ }
+
+ public static class Builder {
+
+ private int bufferSize;
+ private int fragmentSizeHint;
+ private Charset charset;
+ private CodingErrorAction malformedInputAction;
+ private CodingErrorAction unmappableInputAction;
+ private MessageConstraints messageConstraints;
+
+ Builder() {
+ this.fragmentSizeHint = -1;
+ }
+
+ public Builder setBufferSize(final int bufferSize) {
+ this.bufferSize = bufferSize;
+ return this;
+ }
+
+ public Builder setFragmentSizeHint(final int fragmentSizeHint) {
+ this.fragmentSizeHint = fragmentSizeHint;
+ return this;
+ }
+
+ public Builder setCharset(final Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ public Builder setMalformedInputAction(final CodingErrorAction malformedInputAction) {
+ this.malformedInputAction = malformedInputAction;
+ if (malformedInputAction != null && this.charset == null) {
+ this.charset = Consts.ASCII;
+ }
+ return this;
+ }
+
+ public Builder setUnmappableInputAction(final CodingErrorAction unmappableInputAction) {
+ this.unmappableInputAction = unmappableInputAction;
+ if (unmappableInputAction != null && this.charset == null) {
+ this.charset = Consts.ASCII;
+ }
+ return this;
+ }
+
+ public Builder setMessageConstraints(final MessageConstraints messageConstraints) {
+ this.messageConstraints = messageConstraints;
+ return this;
+ }
+
+ public ConnectionConfig build() {
+ Charset cs = charset;
+ if (cs == null && (malformedInputAction != null || unmappableInputAction != null)) {
+ cs = Consts.ASCII;
+ }
+ final int bufSize = this.bufferSize > 0 ? this.bufferSize : 8 * 1024;
+ final int fragmentHintSize = this.fragmentSizeHint >= 0 ? this.fragmentSizeHint : bufSize;
+ return new ConnectionConfig(
+ bufSize,
+ fragmentHintSize,
+ cs,
+ malformedInputAction,
+ unmappableInputAction,
+ messageConstraints);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Lookup.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Lookup.java
new file mode 100644
index 000000000..343dda2d3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Lookup.java
@@ -0,0 +1,40 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.config;
+
+
+/**
+ * Generic lookup by low-case string ID.
+ *
+ * @since 4.3
+ */
+public interface Lookup<I> {
+
+ I lookup(String name);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/MessageConstraints.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/MessageConstraints.java
new file mode 100644
index 000000000..5ac8c065a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/MessageConstraints.java
@@ -0,0 +1,113 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.config;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * HTTP Message constraints: line length and header count.
+ *
+ * @since 4.3
+ */
+public class MessageConstraints implements Cloneable {
+
+ public static final MessageConstraints DEFAULT = new Builder().build();
+
+ private final int maxLineLength;
+ private final int maxHeaderCount;
+
+ MessageConstraints(final int maxLineLength, final int maxHeaderCount) {
+ super();
+ this.maxLineLength = maxLineLength;
+ this.maxHeaderCount = maxHeaderCount;
+ }
+
+ public int getMaxLineLength() {
+ return maxLineLength;
+ }
+
+ public int getMaxHeaderCount() {
+ return maxHeaderCount;
+ }
+
+ @Override
+ protected MessageConstraints clone() throws CloneNotSupportedException {
+ return (MessageConstraints) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[maxLineLength=").append(maxLineLength)
+ .append(", maxHeaderCount=").append(maxHeaderCount)
+ .append("]");
+ return builder.toString();
+ }
+
+ public static MessageConstraints lineLen(final int max) {
+ return new MessageConstraints(Args.notNegative(max, "Max line length"), -1);
+ }
+
+ public static MessageConstraints.Builder custom() {
+ return new Builder();
+ }
+
+ public static MessageConstraints.Builder copy(final MessageConstraints config) {
+ Args.notNull(config, "Message constraints");
+ return new Builder()
+ .setMaxHeaderCount(config.getMaxHeaderCount())
+ .setMaxLineLength(config.getMaxLineLength());
+ }
+
+ public static class Builder {
+
+ private int maxLineLength;
+ private int maxHeaderCount;
+
+ Builder() {
+ this.maxLineLength = -1;
+ this.maxHeaderCount = -1;
+ }
+
+ public Builder setMaxLineLength(final int maxLineLength) {
+ this.maxLineLength = maxLineLength;
+ return this;
+ }
+
+ public Builder setMaxHeaderCount(final int maxHeaderCount) {
+ this.maxHeaderCount = maxHeaderCount;
+ return this;
+ }
+
+ public MessageConstraints build() {
+ return new MessageConstraints(maxLineLength, maxHeaderCount);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Registry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Registry.java
new file mode 100644
index 000000000..71b718bee
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/Registry.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.config;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+/**
+ * Generic registry of items keyed by low-case string ID.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public final class Registry<I> implements Lookup<I> {
+
+ private final Map<String, I> map;
+
+ Registry(final Map<String, I> map) {
+ super();
+ this.map = new ConcurrentHashMap<String, I>(map);
+ }
+
+ public I lookup(final String key) {
+ if (key == null) {
+ return null;
+ }
+ return map.get(key.toLowerCase(Locale.US));
+ }
+
+ @Override
+ public String toString() {
+ return map.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/RegistryBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/RegistryBuilder.java
new file mode 100644
index 000000000..56dbd7976
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/RegistryBuilder.java
@@ -0,0 +1,72 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.config;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Builder for {@link Registry} instances.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public final class RegistryBuilder<I> {
+
+ private final Map<String, I> items;
+
+ public static <I> RegistryBuilder<I> create() {
+ return new RegistryBuilder<I>();
+ }
+
+ RegistryBuilder() {
+ super();
+ this.items = new HashMap<String, I>();
+ }
+
+ public RegistryBuilder<I> register(final String id, final I item) {
+ Args.notEmpty(id, "ID");
+ Args.notNull(item, "Item");
+ items.put(id.toLowerCase(Locale.US), item);
+ return this;
+ }
+
+ public Registry<I> build() {
+ return new Registry<I>(items);
+ }
+
+ @Override
+ public String toString() {
+ return items.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/SocketConfig.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/SocketConfig.java
new file mode 100644
index 000000000..515dac1b1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/SocketConfig.java
@@ -0,0 +1,197 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.config;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Socket configuration.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class SocketConfig implements Cloneable {
+
+ public static final SocketConfig DEFAULT = new Builder().build();
+
+ private final int soTimeout;
+ private final boolean soReuseAddress;
+ private final int soLinger;
+ private final boolean soKeepAlive;
+ private final boolean tcpNoDelay;
+
+ SocketConfig(
+ final int soTimeout,
+ final boolean soReuseAddress,
+ final int soLinger,
+ final boolean soKeepAlive,
+ final boolean tcpNoDelay) {
+ super();
+ this.soTimeout = soTimeout;
+ this.soReuseAddress = soReuseAddress;
+ this.soLinger = soLinger;
+ this.soKeepAlive = soKeepAlive;
+ this.tcpNoDelay = tcpNoDelay;
+ }
+
+ /**
+ * Determines the default socket timeout value for non-blocking I/O operations.
+ * <p/>
+ * Default: <code>0</code> (no timeout)
+ *
+ * @see java.net.SocketOptions#SO_TIMEOUT
+ */
+ public int getSoTimeout() {
+ return soTimeout;
+ }
+
+ /**
+ * Determines the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter
+ * for newly created sockets.
+ * <p/>
+ * Default: <code>false</code>
+ *
+ * @see java.net.SocketOptions#SO_REUSEADDR
+ */
+ public boolean isSoReuseAddress() {
+ return soReuseAddress;
+ }
+
+ /**
+ * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
+ * for newly created sockets.
+ * <p/>
+ * Default: <code>-1</code>
+ *
+ * @see java.net.SocketOptions#SO_LINGER
+ */
+ public int getSoLinger() {
+ return soLinger;
+ }
+
+ /**
+ * Determines the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter
+ * for newly created sockets.
+ * <p/>
+ * Default: <code>-1</code>
+ *
+ * @see java.net.SocketOptions#SO_KEEPALIVE
+ */
+ public boolean isSoKeepAlive() {
+ return this.soKeepAlive;
+ }
+
+ /**
+ * Determines the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter
+ * for newly created sockets.
+ * <p/>
+ * Default: <code>false</code>
+ *
+ * @see java.net.SocketOptions#TCP_NODELAY
+ */
+ public boolean isTcpNoDelay() {
+ return tcpNoDelay;
+ }
+
+ @Override
+ protected SocketConfig clone() throws CloneNotSupportedException {
+ return (SocketConfig) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[soTimeout=").append(this.soTimeout)
+ .append(", soReuseAddress=").append(this.soReuseAddress)
+ .append(", soLinger=").append(this.soLinger)
+ .append(", soKeepAlive=").append(this.soKeepAlive)
+ .append(", tcpNoDelay=").append(this.tcpNoDelay)
+ .append("]");
+ return builder.toString();
+ }
+
+ public static SocketConfig.Builder custom() {
+ return new Builder();
+ }
+
+ public static SocketConfig.Builder copy(final SocketConfig config) {
+ Args.notNull(config, "Socket config");
+ return new Builder()
+ .setSoTimeout(config.getSoTimeout())
+ .setSoReuseAddress(config.isSoReuseAddress())
+ .setSoLinger(config.getSoLinger())
+ .setSoKeepAlive(config.isSoKeepAlive())
+ .setTcpNoDelay(config.isTcpNoDelay());
+ }
+
+ public static class Builder {
+
+ private int soTimeout;
+ private boolean soReuseAddress;
+ private int soLinger;
+ private boolean soKeepAlive;
+ private boolean tcpNoDelay;
+
+ Builder() {
+ this.soLinger = -1;
+ this.tcpNoDelay = true;
+ }
+
+ public Builder setSoTimeout(final int soTimeout) {
+ this.soTimeout = soTimeout;
+ return this;
+ }
+
+ public Builder setSoReuseAddress(final boolean soReuseAddress) {
+ this.soReuseAddress = soReuseAddress;
+ return this;
+ }
+
+ public Builder setSoLinger(final int soLinger) {
+ this.soLinger = soLinger;
+ return this;
+ }
+
+ public Builder setSoKeepAlive(final boolean soKeepAlive) {
+ this.soKeepAlive = soKeepAlive;
+ return this;
+ }
+
+ public Builder setTcpNoDelay(final boolean tcpNoDelay) {
+ this.tcpNoDelay = tcpNoDelay;
+ return this;
+ }
+
+ public SocketConfig build() {
+ return new SocketConfig(soTimeout, soReuseAddress, soLinger, soKeepAlive, tcpNoDelay);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/package-info.java
new file mode 100644
index 000000000..9521d6828
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/config/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Core configuration APIs.
+ */
+package ch.boye.httpclientandroidlib.config;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicEofSensorWatcher.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicEofSensorWatcher.java
new file mode 100644
index 000000000..0273224ad
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicEofSensorWatcher.java
@@ -0,0 +1,105 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of {@link EofSensorWatcher}. The underlying connection
+ * is released on close or EOF.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) do not use.
+ */
+@Deprecated
+@NotThreadSafe
+public class BasicEofSensorWatcher implements EofSensorWatcher {
+
+ /** The connection to auto-release. */
+ protected final ManagedClientConnection managedConn;
+
+ /** Whether to keep the connection alive. */
+ protected final boolean attemptReuse;
+
+ /**
+ * Creates a new watcher for auto-releasing a connection.
+ *
+ * @param conn the connection to auto-release
+ * @param reuse whether the connection should be re-used
+ */
+ public BasicEofSensorWatcher(final ManagedClientConnection conn,
+ final boolean reuse) {
+ Args.notNull(conn, "Connection");
+ managedConn = conn;
+ attemptReuse = reuse;
+ }
+
+ public boolean eofDetected(final InputStream wrapped)
+ throws IOException {
+
+ try {
+ if (attemptReuse) {
+ // there may be some cleanup required, such as
+ // reading trailers after the response body:
+ wrapped.close();
+ managedConn.markReusable();
+ }
+ } finally {
+ managedConn.releaseConnection();
+ }
+ return false;
+ }
+
+ public boolean streamClosed(final InputStream wrapped)
+ throws IOException {
+
+ try {
+ if (attemptReuse) {
+ // this assumes that closing the stream will
+ // consume the remainder of the response body:
+ wrapped.close();
+ managedConn.markReusable();
+ }
+ } finally {
+ managedConn.releaseConnection();
+ }
+ return false;
+ }
+
+ public boolean streamAbort(final InputStream wrapped)
+ throws IOException {
+
+ managedConn.abortConnection();
+ return false;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicManagedEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicManagedEntity.java
new file mode 100644
index 000000000..59556b5e9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicManagedEntity.java
@@ -0,0 +1,208 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.SocketException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * An entity that releases a {@link ManagedClientConnection connection}.
+ * A {@link ManagedClientConnection} will
+ * typically <i>not</i> return a managed entity, but you can replace
+ * the unmanaged entity in the response with a managed one.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) do not use.
+ */
+@Deprecated
+@NotThreadSafe
+public class BasicManagedEntity extends HttpEntityWrapper
+ implements ConnectionReleaseTrigger, EofSensorWatcher {
+
+ /** The connection to release. */
+ protected ManagedClientConnection managedConn;
+
+ /** Whether to keep the connection alive. */
+ protected final boolean attemptReuse;
+
+ /**
+ * Creates a new managed entity that can release a connection.
+ *
+ * @param entity the entity of which to wrap the content.
+ * Note that the argument entity can no longer be used
+ * afterwards, since the content will be taken by this
+ * managed entity.
+ * @param conn the connection to release
+ * @param reuse whether the connection should be re-used
+ */
+ public BasicManagedEntity(final HttpEntity entity,
+ final ManagedClientConnection conn,
+ final boolean reuse) {
+ super(entity);
+ Args.notNull(conn, "Connection");
+ this.managedConn = conn;
+ this.attemptReuse = reuse;
+ }
+
+ @Override
+ public boolean isRepeatable() {
+ return false;
+ }
+
+ @Override
+ public InputStream getContent() throws IOException {
+ return new EofSensorInputStream(wrappedEntity.getContent(), this);
+ }
+
+ private void ensureConsumed() throws IOException {
+ if (managedConn == null) {
+ return;
+ }
+
+ try {
+ if (attemptReuse) {
+ // this will not trigger a callback from EofSensorInputStream
+ EntityUtils.consume(wrappedEntity);
+ managedConn.markReusable();
+ } else {
+ managedConn.unmarkReusable();
+ }
+ } finally {
+ releaseManagedConnection();
+ }
+ }
+
+ /**
+ * @deprecated (4.1) Use {@link EntityUtils#consume(HttpEntity)}
+ */
+ @Deprecated
+ @Override
+ public void consumeContent() throws IOException {
+ ensureConsumed();
+ }
+
+ @Override
+ public void writeTo(final OutputStream outstream) throws IOException {
+ super.writeTo(outstream);
+ ensureConsumed();
+ }
+
+ public void releaseConnection() throws IOException {
+ ensureConsumed();
+ }
+
+ public void abortConnection() throws IOException {
+
+ if (managedConn != null) {
+ try {
+ managedConn.abortConnection();
+ } finally {
+ managedConn = null;
+ }
+ }
+ }
+
+ public boolean eofDetected(final InputStream wrapped) throws IOException {
+ try {
+ if (managedConn != null) {
+ if (attemptReuse) {
+ // there may be some cleanup required, such as
+ // reading trailers after the response body:
+ wrapped.close();
+ managedConn.markReusable();
+ } else {
+ managedConn.unmarkReusable();
+ }
+ }
+ } finally {
+ releaseManagedConnection();
+ }
+ return false;
+ }
+
+ public boolean streamClosed(final InputStream wrapped) throws IOException {
+ try {
+ if (managedConn != null) {
+ if (attemptReuse) {
+ final boolean valid = managedConn.isOpen();
+ // this assumes that closing the stream will
+ // consume the remainder of the response body:
+ try {
+ wrapped.close();
+ managedConn.markReusable();
+ } catch (final SocketException ex) {
+ if (valid) {
+ throw ex;
+ }
+ }
+ } else {
+ managedConn.unmarkReusable();
+ }
+ }
+ } finally {
+ releaseManagedConnection();
+ }
+ return false;
+ }
+
+ public boolean streamAbort(final InputStream wrapped) throws IOException {
+ if (managedConn != null) {
+ managedConn.abortConnection();
+ }
+ return false;
+ }
+
+ /**
+ * Releases the connection gracefully.
+ * The connection attribute will be nullified.
+ * Subsequent invocations are no-ops.
+ *
+ * @throws IOException in case of an IO problem.
+ * The connection attribute will be nullified anyway.
+ */
+ protected void releaseManagedConnection()
+ throws IOException {
+
+ if (managedConn != null) {
+ try {
+ managedConn.releaseConnection();
+ } finally {
+ managedConn = null;
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManager.java
new file mode 100644
index 000000000..dcdbb4ce5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManager.java
@@ -0,0 +1,117 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+
+/**
+ * Management interface for {@link ManagedClientConnection client connections}.
+ * The purpose of an HTTP connection manager is to serve as a factory for new
+ * HTTP connections, manage persistent connections and synchronize access to
+ * persistent connections making sure that only one thread of execution can
+ * have access to a connection at a time.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}.
+ */
+@Deprecated
+public interface ClientConnectionManager {
+
+ /**
+ * Obtains the scheme registry used by this manager.
+ *
+ * @return the scheme registry, never <code>null</code>
+ */
+ SchemeRegistry getSchemeRegistry();
+
+ /**
+ * Returns a new {@link ClientConnectionRequest}, from which a
+ * {@link ManagedClientConnection} can be obtained or the request can be
+ * aborted.
+ */
+ ClientConnectionRequest requestConnection(HttpRoute route, Object state);
+
+ /**
+ * Releases a connection for use by others.
+ * You may optionally specify how long the connection is valid
+ * to be reused. Values <= 0 are considered to be valid forever.
+ * If the connection is not marked as reusable, the connection will
+ * not be reused regardless of the valid duration.
+ *
+ * If the connection has been released before,
+ * the call will be ignored.
+ *
+ * @param conn the connection to release
+ * @param validDuration the duration of time this connection is valid for reuse
+ * @param timeUnit the unit of time validDuration is measured in
+ *
+ * @see #closeExpiredConnections()
+ */
+ void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit);
+
+ /**
+ * Closes idle connections in the pool.
+ * Open connections in the pool that have not been used for the
+ * timespan given by the argument will be closed.
+ * Currently allocated connections are not subject to this method.
+ * Times will be checked with milliseconds precision
+ *
+ * All expired connections will also be closed.
+ *
+ * @param idletime the idle time of connections to be closed
+ * @param tunit the unit for the <code>idletime</code>
+ *
+ * @see #closeExpiredConnections()
+ */
+ void closeIdleConnections(long idletime, TimeUnit tunit);
+
+ /**
+ * Closes all expired connections in the pool.
+ * Open connections in the pool that have not been used for
+ * the timespan defined when the connection was released will be closed.
+ * Currently allocated connections are not subject to this method.
+ * Times will be checked with milliseconds precision.
+ */
+ void closeExpiredConnections();
+
+ /**
+ * Shuts down this connection manager and releases allocated resources.
+ * This includes closing all connections, whether they are currently
+ * used or not.
+ */
+ void shutdown();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManagerFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManagerFactory.java
new file mode 100644
index 000000000..895690e95
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManagerFactory.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * A factory for creating new {@link ClientConnectionManager} instances.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}.
+ */
+@Deprecated
+public interface ClientConnectionManagerFactory {
+
+ ClientConnectionManager newInstance(
+ HttpParams params,
+ SchemeRegistry schemeRegistry);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionOperator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionOperator.java
new file mode 100644
index 000000000..333975b2c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionOperator.java
@@ -0,0 +1,107 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * ClientConnectionOperator represents a strategy for creating
+ * {@link OperatedClientConnection} instances and updating the underlying
+ * {@link java.net.Socket} of those objects. Implementations will most
+ * likely make use of {@link ch.boye.httpclientandroidlib.conn.scheme.SchemeSocketFactory}s
+ * to create {@link java.net.Socket} instances.
+ * <p>
+ * The methods in this interface allow the creation of plain and layered
+ * sockets. Creating a tunnelled connection through a proxy, however,
+ * is not within the scope of the operator.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}.
+ */
+@Deprecated
+public interface ClientConnectionOperator {
+
+ /**
+ * Creates a new connection that can be operated.
+ *
+ * @return a new, unopened connection for use with this operator
+ */
+ OperatedClientConnection createConnection();
+
+ /**
+ * Opens a connection to the given target host.
+ *
+ * @param conn the connection to open
+ * @param target the target host to connect to
+ * @param local the local address to route from, or
+ * <code>null</code> for the default
+ * @param context the context for the connection
+ * @param params the parameters for the connection
+ *
+ * @throws IOException in case of a problem
+ */
+ void openConnection(OperatedClientConnection conn,
+ HttpHost target,
+ InetAddress local,
+ HttpContext context,
+ HttpParams params)
+ throws IOException;
+
+ /**
+ * Updates a connection with a layered secure connection.
+ * The typical use of this method is to update a tunnelled plain
+ * connection (HTTP) to a secure TLS/SSL connection (HTTPS).
+ *
+ * @param conn the open connection to update
+ * @param target the target host for the updated connection.
+ * The connection must already be open or tunnelled
+ * to the host and port, but the scheme of the target
+ * will be used to create a layered connection.
+ * @param context the context for the connection
+ * @param params the parameters for the updated connection
+ *
+ * @throws IOException in case of a problem
+ */
+ void updateSecureConnection(OperatedClientConnection conn,
+ HttpHost target,
+ HttpContext context,
+ HttpParams params)
+ throws IOException;
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionRequest.java
new file mode 100644
index 000000000..656284081
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionRequest.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Encapsulates a request for a {@link ManagedClientConnection}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) replaced by {@link ConnectionRequest}.
+ */
+@Deprecated
+public interface ClientConnectionRequest {
+
+ /**
+ * Obtains a connection within a given time.
+ * This method will block until a connection becomes available,
+ * the timeout expires, or the connection manager is
+ * {@link ClientConnectionManager#shutdown() shut down}.
+ * Timeouts are handled with millisecond precision.
+ *
+ * If {@link #abortRequest()} is called while this is blocking or
+ * before this began, an {@link InterruptedException} will
+ * be thrown.
+ *
+ * @param timeout the timeout, 0 or negative for no timeout
+ * @param tunit the unit for the <code>timeout</code>,
+ * may be <code>null</code> only if there is no timeout
+ *
+ * @return a connection that can be used to communicate
+ * along the given route
+ *
+ * @throws ConnectionPoolTimeoutException
+ * in case of a timeout
+ * @throws InterruptedException
+ * if the calling thread is interrupted while waiting
+ */
+ ManagedClientConnection getConnection(long timeout, TimeUnit tunit)
+ throws InterruptedException, ConnectionPoolTimeoutException;
+
+ /**
+ * Aborts the call to {@link #getConnection(long, TimeUnit)},
+ * causing it to throw an {@link InterruptedException}.
+ */
+ void abortRequest();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectTimeoutException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectTimeoutException.java
new file mode 100644
index 000000000..f98bd1941
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectTimeoutException.java
@@ -0,0 +1,94 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetAddress;
+import java.util.Arrays;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * A timeout while connecting to an HTTP server or waiting for an
+ * available connection from an HttpConnectionManager.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ConnectTimeoutException extends InterruptedIOException {
+
+ private static final long serialVersionUID = -4816682903149535989L;
+
+ private final HttpHost host;
+
+ /**
+ * Creates a ConnectTimeoutException with a <tt>null</tt> detail message.
+ */
+ public ConnectTimeoutException() {
+ super();
+ this.host = null;
+ }
+
+ /**
+ * Creates a ConnectTimeoutException with the specified detail message.
+ */
+ public ConnectTimeoutException(final String message) {
+ super(message);
+ this.host = null;
+ }
+
+ /**
+ * Creates a ConnectTimeoutException based on original {@link IOException}.
+ *
+ * @since 4.3
+ */
+ public ConnectTimeoutException(
+ final IOException cause,
+ final HttpHost host,
+ final InetAddress... remoteAddresses) {
+ super("Connect to " +
+ (host != null ? host.toHostString() : "remote host") +
+ (remoteAddresses != null && remoteAddresses.length > 0 ?
+ " " + Arrays.asList(remoteAddresses) : "") +
+ ((cause != null && cause.getMessage() != null) ?
+ " failed: " + cause.getMessage() : " timed out"));
+ this.host = host;
+ initCause(cause);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public HttpHost getHost() {
+ return host;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java
new file mode 100644
index 000000000..3f06e4873
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Interface for deciding how long a connection can remain
+ * idle before being reused.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ */
+public interface ConnectionKeepAliveStrategy {
+
+ /**
+ * Returns the duration of time which this connection can be safely kept
+ * idle. If the connection is left idle for longer than this period of time,
+ * it MUST not reused. A value of 0 or less may be returned to indicate that
+ * there is no suitable suggestion.
+ *
+ * When coupled with a {@link ch.boye.httpclientandroidlib.ConnectionReuseStrategy}, if
+ * {@link ch.boye.httpclientandroidlib.ConnectionReuseStrategy#keepAlive(
+ * HttpResponse, HttpContext)} returns true, this allows you to control
+ * how long the reuse will last. If keepAlive returns false, this should
+ * have no meaningful impact
+ *
+ * @param response
+ * The last response received over the connection.
+ * @param context
+ * the context in which the connection is being used.
+ *
+ * @return the duration in ms for which it is safe to keep the connection
+ * idle, or <=0 if no suggested duration.
+ */
+ long getKeepAliveDuration(HttpResponse response, HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java
new file mode 100644
index 000000000..d4066b2a3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * A timeout while waiting for an available connection
+ * from a connection manager.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ConnectionPoolTimeoutException extends ConnectTimeoutException {
+
+ private static final long serialVersionUID = -7898874842020245128L;
+
+ /**
+ * Creates a ConnectTimeoutException with a <tt>null</tt> detail message.
+ */
+ public ConnectionPoolTimeoutException() {
+ super();
+ }
+
+ /**
+ * Creates a ConnectTimeoutException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public ConnectionPoolTimeoutException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionReleaseTrigger.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionReleaseTrigger.java
new file mode 100644
index 000000000..97269268b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionReleaseTrigger.java
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+
+/**
+ * Interface for releasing a connection. This can be implemented by various
+ * "trigger" objects which are associated with a connection, for example
+ * a {@link EofSensorInputStream stream} or an {@link BasicManagedEntity entity}
+ * or the {@link ManagedClientConnection connection} itself.
+ * <p>
+ * The methods in this interface can safely be called multiple times.
+ * The first invocation releases the connection, subsequent calls
+ * are ignored.
+ *
+ * @since 4.0
+ */
+public interface ConnectionReleaseTrigger {
+
+ /**
+ * Releases the connection with the option of keep-alive. This is a
+ * "graceful" release and may cause IO operations for consuming the
+ * remainder of a response entity. Use
+ * {@link #abortConnection abortConnection} for a hard release. The
+ * connection may be reused as specified by the duration.
+ *
+ * @throws IOException
+ * in case of an IO problem. The connection will be released
+ * anyway.
+ */
+ void releaseConnection()
+ throws IOException;
+
+ /**
+ * Releases the connection without the option of keep-alive.
+ * This is a "hard" release that implies a shutdown of the connection.
+ * Use {@link #releaseConnection()} for a graceful release.
+ *
+ * @throws IOException in case of an IO problem.
+ * The connection will be released anyway.
+ */
+ void abortConnection()
+ throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionRequest.java
new file mode 100644
index 000000000..838c35567
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionRequest.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.concurrent.Cancellable;
+
+/**
+ * Represents a request for a {@link HttpClientConnection} whose life cycle
+ * is managed by a connection manager.
+ *
+ * @since 4.3
+ */
+public interface ConnectionRequest extends Cancellable {
+
+ /**
+ * Obtains a connection within a given time.
+ * This method will block until a connection becomes available,
+ * the timeout expires, or the connection manager is shut down.
+ * Timeouts are handled with millisecond precision.
+ *
+ * If {@link #cancel()} is called while this is blocking or
+ * before this began, an {@link InterruptedException} will
+ * be thrown.
+ *
+ * @param timeout the timeout, 0 or negative for no timeout
+ * @param tunit the unit for the <code>timeout</code>,
+ * may be <code>null</code> only if there is no timeout
+ *
+ * @return a connection that can be used to communicate
+ * along the given route
+ *
+ * @throws ConnectionPoolTimeoutException
+ * in case of a timeout
+ * @throws InterruptedException
+ * if the calling thread is interrupted while waiting
+ */
+ HttpClientConnection get(long timeout, TimeUnit tunit)
+ throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/DnsResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/DnsResolver.java
new file mode 100644
index 000000000..78ce8709b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/DnsResolver.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Users may implement this interface to override the normal DNS lookup offered
+ * by the OS.
+ *
+ * @since 4.2
+ */
+public interface DnsResolver {
+
+ /**
+ * Returns the IP address for the specified host name, or null if the given
+ * host is not recognized or the associated IP address cannot be used to
+ * build an InetAddress instance.
+ *
+ * @see InetAddress
+ *
+ * @param host
+ * The host name to be resolved by this resolver.
+ * @return The IP address associated to the given host name, or null if the
+ * host name is not known by the implementation class.
+ */
+ InetAddress[] resolve(String host) throws UnknownHostException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorInputStream.java
new file mode 100644
index 000000000..7db23eed4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorInputStream.java
@@ -0,0 +1,289 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A stream wrapper that triggers actions on {@link #close close()} and EOF.
+ * Primarily used to auto-release an underlying managed connection when the response
+ * body is consumed or no longer needed.
+ *
+ * @see EofSensorWatcher
+ *
+ * @since 4.0
+ */
+// don't use FilterInputStream as the base class, we'd have to
+// override markSupported(), mark(), and reset() to disable them
+@NotThreadSafe
+public class EofSensorInputStream extends InputStream implements ConnectionReleaseTrigger {
+
+ /**
+ * The wrapped input stream, while accessible.
+ * The value changes to <code>null</code> when the wrapped stream
+ * becomes inaccessible.
+ */
+ protected InputStream wrappedStream;
+
+ /**
+ * Indicates whether this stream itself is closed.
+ * If it isn't, but {@link #wrappedStream wrappedStream}
+ * is <code>null</code>, we're running in EOF mode.
+ * All read operations will indicate EOF without accessing
+ * the underlying stream. After closing this stream, read
+ * operations will trigger an {@link IOException IOException}.
+ *
+ * @see #isReadAllowed isReadAllowed
+ */
+ private boolean selfClosed;
+
+ /** The watcher to be notified, if any. */
+ private final EofSensorWatcher eofWatcher;
+
+ /**
+ * Creates a new EOF sensor.
+ * If no watcher is passed, the underlying stream will simply be
+ * closed when EOF is detected or {@link #close close} is called.
+ * Otherwise, the watcher decides whether the underlying stream
+ * should be closed before detaching from it.
+ *
+ * @param in the wrapped stream
+ * @param watcher the watcher for events, or <code>null</code> for
+ * auto-close behavior without notification
+ */
+ public EofSensorInputStream(final InputStream in,
+ final EofSensorWatcher watcher) {
+ Args.notNull(in, "Wrapped stream");
+ wrappedStream = in;
+ selfClosed = false;
+ eofWatcher = watcher;
+ }
+
+ boolean isSelfClosed() {
+ return selfClosed;
+ }
+
+ InputStream getWrappedStream() {
+ return wrappedStream;
+ }
+
+ /**
+ * Checks whether the underlying stream can be read from.
+ *
+ * @return <code>true</code> if the underlying stream is accessible,
+ * <code>false</code> if this stream is in EOF mode and
+ * detached from the underlying stream
+ *
+ * @throws IOException if this stream is already closed
+ */
+ protected boolean isReadAllowed() throws IOException {
+ if (selfClosed) {
+ throw new IOException("Attempted read on closed stream.");
+ }
+ return (wrappedStream != null);
+ }
+
+ @Override
+ public int read() throws IOException {
+ int l = -1;
+
+ if (isReadAllowed()) {
+ try {
+ l = wrappedStream.read();
+ checkEOF(l);
+ } catch (final IOException ex) {
+ checkAbort();
+ throw ex;
+ }
+ }
+
+ return l;
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ int l = -1;
+
+ if (isReadAllowed()) {
+ try {
+ l = wrappedStream.read(b, off, len);
+ checkEOF(l);
+ } catch (final IOException ex) {
+ checkAbort();
+ throw ex;
+ }
+ }
+
+ return l;
+ }
+
+ @Override
+ public int read(final byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public int available() throws IOException {
+ int a = 0; // not -1
+
+ if (isReadAllowed()) {
+ try {
+ a = wrappedStream.available();
+ // no checkEOF() here, available() can't trigger EOF
+ } catch (final IOException ex) {
+ checkAbort();
+ throw ex;
+ }
+ }
+
+ return a;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // tolerate multiple calls to close()
+ selfClosed = true;
+ checkClose();
+ }
+
+ /**
+ * Detects EOF and notifies the watcher.
+ * This method should only be called while the underlying stream is
+ * still accessible. Use {@link #isReadAllowed isReadAllowed} to
+ * check that condition.
+ * <br/>
+ * If EOF is detected, the watcher will be notified and this stream
+ * is detached from the underlying stream. This prevents multiple
+ * notifications from this stream.
+ *
+ * @param eof the result of the calling read operation.
+ * A negative value indicates that EOF is reached.
+ *
+ * @throws IOException
+ * in case of an IO problem on closing the underlying stream
+ */
+ protected void checkEOF(final int eof) throws IOException {
+
+ if ((wrappedStream != null) && (eof < 0)) {
+ try {
+ boolean scws = true; // should close wrapped stream?
+ if (eofWatcher != null) {
+ scws = eofWatcher.eofDetected(wrappedStream);
+ }
+ if (scws) {
+ wrappedStream.close();
+ }
+ } finally {
+ wrappedStream = null;
+ }
+ }
+ }
+
+ /**
+ * Detects stream close and notifies the watcher.
+ * There's not much to detect since this is called by {@link #close close}.
+ * The watcher will only be notified if this stream is closed
+ * for the first time and before EOF has been detected.
+ * This stream will be detached from the underlying stream to prevent
+ * multiple notifications to the watcher.
+ *
+ * @throws IOException
+ * in case of an IO problem on closing the underlying stream
+ */
+ protected void checkClose() throws IOException {
+
+ if (wrappedStream != null) {
+ try {
+ boolean scws = true; // should close wrapped stream?
+ if (eofWatcher != null) {
+ scws = eofWatcher.streamClosed(wrappedStream);
+ }
+ if (scws) {
+ wrappedStream.close();
+ }
+ } finally {
+ wrappedStream = null;
+ }
+ }
+ }
+
+ /**
+ * Detects stream abort and notifies the watcher.
+ * There's not much to detect since this is called by
+ * {@link #abortConnection abortConnection}.
+ * The watcher will only be notified if this stream is aborted
+ * for the first time and before EOF has been detected or the
+ * stream has been {@link #close closed} gracefully.
+ * This stream will be detached from the underlying stream to prevent
+ * multiple notifications to the watcher.
+ *
+ * @throws IOException
+ * in case of an IO problem on closing the underlying stream
+ */
+ protected void checkAbort() throws IOException {
+
+ if (wrappedStream != null) {
+ try {
+ boolean scws = true; // should close wrapped stream?
+ if (eofWatcher != null) {
+ scws = eofWatcher.streamAbort(wrappedStream);
+ }
+ if (scws) {
+ wrappedStream.close();
+ }
+ } finally {
+ wrappedStream = null;
+ }
+ }
+ }
+
+ /**
+ * Same as {@link #close close()}.
+ */
+ public void releaseConnection() throws IOException {
+ close();
+ }
+
+ /**
+ * Aborts this stream.
+ * This is a special version of {@link #close close()} which prevents
+ * re-use of the underlying connection, if any. Calling this method
+ * indicates that there should be no attempt to read until the end of
+ * the stream.
+ */
+ public void abortConnection() throws IOException {
+ // tolerate multiple calls
+ selfClosed = true;
+ checkAbort();
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorWatcher.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorWatcher.java
new file mode 100644
index 000000000..c57772fb8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorWatcher.java
@@ -0,0 +1,95 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A watcher for {@link EofSensorInputStream}. Each stream will notify its
+ * watcher at most once.
+ *
+ * @since 4.0
+ */
+public interface EofSensorWatcher {
+
+ /**
+ * Indicates that EOF is detected.
+ *
+ * @param wrapped the underlying stream which has reached EOF
+ *
+ * @return <code>true</code> if <code>wrapped</code> should be closed,
+ * <code>false</code> if it should be left alone
+ *
+ * @throws IOException
+ * in case of an IO problem, for example if the watcher itself
+ * closes the underlying stream. The caller will leave the
+ * wrapped stream alone, as if <code>false</code> was returned.
+ */
+ boolean eofDetected(InputStream wrapped)
+ throws IOException;
+
+ /**
+ * Indicates that the {@link EofSensorInputStream stream} is closed.
+ * This method will be called only if EOF was <i>not</i> detected
+ * before closing. Otherwise, {@link #eofDetected eofDetected} is called.
+ *
+ * @param wrapped the underlying stream which has not reached EOF
+ *
+ * @return <code>true</code> if <code>wrapped</code> should be closed,
+ * <code>false</code> if it should be left alone
+ *
+ * @throws IOException
+ * in case of an IO problem, for example if the watcher itself
+ * closes the underlying stream. The caller will leave the
+ * wrapped stream alone, as if <code>false</code> was returned.
+ */
+ boolean streamClosed(InputStream wrapped)
+ throws IOException;
+
+ /**
+ * Indicates that the {@link EofSensorInputStream stream} is aborted.
+ * This method will be called only if EOF was <i>not</i> detected
+ * before aborting. Otherwise, {@link #eofDetected eofDetected} is called.
+ * <p/>
+ * This method will also be invoked when an input operation causes an
+ * IOException to be thrown to make sure the input stream gets shut down.
+ *
+ * @param wrapped the underlying stream which has not reached EOF
+ *
+ * @return <code>true</code> if <code>wrapped</code> should be closed,
+ * <code>false</code> if it should be left alone
+ *
+ * @throws IOException
+ * in case of an IO problem, for example if the watcher itself
+ * closes the underlying stream. The caller will leave the
+ * wrapped stream alone, as if <code>false</code> was returned.
+ */
+ boolean streamAbort(InputStream wrapped)
+ throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpClientConnectionManager.java
new file mode 100644
index 000000000..0381a803f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpClientConnectionManager.java
@@ -0,0 +1,176 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Represents a manager of persistent client connections.
+ * <p/>
+ * The purpose of an HTTP connection manager is to serve as a factory for new
+ * HTTP connections, manage persistent connections and synchronize access to
+ * persistent connections making sure that only one thread of execution can
+ * have access to a connection at a time.
+ * <p/>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.3
+ */
+public interface HttpClientConnectionManager {
+
+ /**
+ * Returns a new {@link ConnectionRequest}, from which a
+ * {@link HttpClientConnection} can be obtained or the request can be
+ * aborted.
+ * <p/>
+ * Please note that newly allocated connections can be returned
+ * in the closed state. The consumer of that connection is responsible
+ * for fully establishing the route the to the connection target
+ * by calling {@link #connect(ch.boye.httpclientandroidlib.HttpClientConnection,
+ * ch.boye.httpclientandroidlib.conn.routing.HttpRoute, int,
+ * ch.boye.httpclientandroidlib.protocol.HttpContext) connect} in order to connect
+ * directly to the target or to the first proxy hop, optionally calling
+ * {@link #upgrade(ch.boye.httpclientandroidlib.HttpClientConnection,
+ * ch.boye.httpclientandroidlib.conn.routing.HttpRoute,
+ * ch.boye.httpclientandroidlib.protocol.HttpContext) upgrade} method to upgrade
+ * the connection after having executed <code>CONNECT</code> method to
+ * all intermediate proxy hops and and finally calling {@link #routeComplete(
+ * ch.boye.httpclientandroidlib.HttpClientConnection,
+ * ch.boye.httpclientandroidlib.conn.routing.HttpRoute,
+ * ch.boye.httpclientandroidlib.protocol.HttpContext) routeComplete} to mark the route
+ * as fully completed.
+ *
+ * @param route HTTP route of the requested connection.
+ * @param state expected state of the connection or <code>null</code>
+ * if the connection is not expected to carry any state.
+ */
+ ConnectionRequest requestConnection(HttpRoute route, Object state);
+
+ /**
+ * Releases the connection back to the manager making it potentially
+ * re-usable by other consumers. Optionally, the maximum period
+ * of how long the manager should keep the connection alive can be
+ * defined using <code>validDuration</code> and <code>timeUnit</code>
+ * parameters.
+ *
+ * @param conn the managed connection to release.
+ * @param validDuration the duration of time this connection is valid for reuse.
+ * @param timeUnit the time unit.
+ *
+ * @see #closeExpiredConnections()
+ */
+ void releaseConnection(
+ HttpClientConnection conn, Object newState, long validDuration, TimeUnit timeUnit);
+
+ /**
+ * Connects the underlying connection socket to the connection target in case
+ * of a direct route or to the first proxy hop in case of a route via a proxy
+ * (or multiple proxies).
+ *
+ * @param conn the managed connection.
+ * @param route the route of the connection.
+ * @param connectTimeout connect timeout in milliseconds.
+ * @param context the actual HTTP context.
+ * @throws IOException
+ */
+ void connect(
+ HttpClientConnection conn,
+ HttpRoute route,
+ int connectTimeout,
+ HttpContext context) throws IOException;
+
+ /**
+ * Upgrades the underlying connection socket to TLS/SSL (or another layering
+ * protocol) after having executed <code>CONNECT</code> method to all
+ * intermediate proxy hops
+ *
+ * @param conn the managed connection.
+ * @param route the route of the connection.
+ * @param context the actual HTTP context.
+ * @throws IOException
+ */
+ void upgrade(
+ HttpClientConnection conn,
+ HttpRoute route,
+ HttpContext context) throws IOException;
+
+ /**
+ * Marks the connection as fully established with all its intermediate
+ * hops completed.
+ *
+ * @param conn the managed connection.
+ * @param route the route of the connection.
+ * @param context the actual HTTP context.
+ * @throws IOException
+ */
+ void routeComplete(
+ HttpClientConnection conn,
+ HttpRoute route,
+ HttpContext context) throws IOException;
+
+ /**
+ * Closes idle connections in the pool.
+ * <p/>
+ * Open connections in the pool that have not been used for the
+ * timespan given by the argument will be closed.
+ * Currently allocated connections are not subject to this method.
+ * Times will be checked with milliseconds precision
+ *
+ * All expired connections will also be closed.
+ *
+ * @param idletime the idle time of connections to be closed
+ * @param tunit the unit for the <code>idletime</code>
+ *
+ * @see #closeExpiredConnections()
+ */
+ void closeIdleConnections(long idletime, TimeUnit tunit);
+
+ /**
+ * Closes all expired connections in the pool.
+ * <p/>
+ * Open connections in the pool that have not been used for
+ * the timespan defined when the connection was released will be closed.
+ * Currently allocated connections are not subject to this method.
+ * Times will be checked with milliseconds precision.
+ */
+ void closeExpiredConnections();
+
+ /**
+ * Shuts down this connection manager and releases allocated resources.
+ * This includes closing all connections, whether they are currently
+ * used or not.
+ */
+ void shutdown();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpConnectionFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpConnectionFactory.java
new file mode 100644
index 000000000..be910921f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpConnectionFactory.java
@@ -0,0 +1,41 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import ch.boye.httpclientandroidlib.HttpConnection;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+
+/**
+ * Generic {@link HttpConnection} factory.
+ *
+ * @since 4.3
+ */
+public interface HttpConnectionFactory<T, C extends HttpConnection> {
+
+ C create(T route, ConnectionConfig config);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpHostConnectException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpHostConnectException.java
new file mode 100644
index 000000000..9b1a1c57a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpHostConnectException.java
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.util.Arrays;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * A {@link ConnectException} that specifies the {@link HttpHost} that was
+ * being connected to.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class HttpHostConnectException extends ConnectException {
+
+ private static final long serialVersionUID = -3194482710275220224L;
+
+ private final HttpHost host;
+
+ /**
+ * @deprecated (4.3) use {@link #HttpHostConnectException(java.io.IOException, ch.boye.httpclientandroidlib.HttpHost,
+ * java.net.InetAddress...)}
+ */
+ @Deprecated
+ public HttpHostConnectException(final HttpHost host, final ConnectException cause) {
+ this(cause, host, null);
+ }
+
+ /**
+ * Creates a HttpHostConnectException based on original {@link java.io.IOException}.
+ *
+ * @since 4.3
+ */
+ public HttpHostConnectException(
+ final IOException cause,
+ final HttpHost host,
+ final InetAddress... remoteAddresses) {
+ super("Connect to " +
+ (host != null ? host.toHostString() : "remote host") +
+ (remoteAddresses != null && remoteAddresses .length > 0 ?
+ " " + Arrays.asList(remoteAddresses) : "") +
+ ((cause != null && cause.getMessage() != null) ?
+ " failed: " + cause.getMessage() : " refused"));
+ this.host = host;
+ initCause(cause);
+ }
+
+ public HttpHost getHost() {
+ return this.host;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpInetSocketAddress.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpInetSocketAddress.java
new file mode 100644
index 000000000..3bd878d21
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpInetSocketAddress.java
@@ -0,0 +1,65 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Extended {@link InetSocketAddress} implementation that also provides access to the original
+ * {@link HttpHost} used to resolve the address.
+ *
+ * @since 4.2 no longer used.
+ *
+ * @deprecated (4.3)
+ */
+@Deprecated
+public class HttpInetSocketAddress extends InetSocketAddress {
+
+ private static final long serialVersionUID = -6650701828361907957L;
+
+ private final HttpHost httphost;
+
+ public HttpInetSocketAddress(final HttpHost httphost, final InetAddress addr, final int port) {
+ super(addr, port);
+ Args.notNull(httphost, "HTTP host");
+ this.httphost = httphost;
+ }
+
+ public HttpHost getHttpHost() {
+ return this.httphost;
+ }
+
+ @Override
+ public String toString() {
+ return this.httphost.getHostName() + ":" + getPort();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpRoutedConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpRoutedConnection.java
new file mode 100644
index 000000000..956e61208
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpRoutedConnection.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import javax.net.ssl.SSLSession;
+
+import ch.boye.httpclientandroidlib.HttpInetConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+
+/**
+ * Interface to access routing information of a client side connection.
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}.
+ */
+@Deprecated
+public interface HttpRoutedConnection extends HttpInetConnection {
+
+ /**
+ * Indicates whether this connection is secure.
+ * The return value is well-defined only while the connection is open.
+ * It may change even while the connection is open.
+ *
+ * @return <code>true</code> if this connection is secure,
+ * <code>false</code> otherwise
+ */
+ boolean isSecure();
+
+ /**
+ * Obtains the current route of this connection.
+ *
+ * @return the route established so far, or
+ * <code>null</code> if not connected
+ */
+ HttpRoute getRoute();
+
+ /**
+ * Obtains the SSL session of the underlying connection, if any.
+ * If this connection is open, and the underlying socket is an
+ * {@link javax.net.ssl.SSLSocket SSLSocket}, the SSL session of
+ * that socket is obtained. This is a potentially blocking operation.
+ * <br/>
+ * <b>Note:</b> Whether the underlying socket is an SSL socket
+ * can not necessarily be determined via {@link #isSecure}.
+ * Plain sockets may be considered secure, for example if they are
+ * connected to a known host in the same network segment.
+ * On the other hand, SSL sockets may be considered insecure,
+ * for example depending on the chosen cipher suite.
+ *
+ * @return the underlying SSL session if available,
+ * <code>null</code> otherwise
+ */
+ SSLSession getSSLSession();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedClientConnection.java
new file mode 100644
index 000000000..a54567b4f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedClientConnection.java
@@ -0,0 +1,228 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLSession;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A client-side connection with advanced connection logic.
+ * Instances are typically obtained from a connection manager.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}.
+ */
+@Deprecated
+public interface ManagedClientConnection extends
+ HttpClientConnection, HttpRoutedConnection, ManagedHttpClientConnection, ConnectionReleaseTrigger {
+
+ /**
+ * Indicates whether this connection is secure.
+ * The return value is well-defined only while the connection is open.
+ * It may change even while the connection is open.
+ *
+ * @return <code>true</code> if this connection is secure,
+ * <code>false</code> otherwise
+ */
+ boolean isSecure();
+
+ /**
+ * Obtains the current route of this connection.
+ *
+ * @return the route established so far, or
+ * <code>null</code> if not connected
+ */
+ HttpRoute getRoute();
+
+ /**
+ * Obtains the SSL session of the underlying connection, if any.
+ * If this connection is open, and the underlying socket is an
+ * {@link javax.net.ssl.SSLSocket SSLSocket}, the SSL session of
+ * that socket is obtained. This is a potentially blocking operation.
+ * <br/>
+ * <b>Note:</b> Whether the underlying socket is an SSL socket
+ * can not necessarily be determined via {@link #isSecure}.
+ * Plain sockets may be considered secure, for example if they are
+ * connected to a known host in the same network segment.
+ * On the other hand, SSL sockets may be considered insecure,
+ * for example depending on the chosen cipher suite.
+ *
+ * @return the underlying SSL session if available,
+ * <code>null</code> otherwise
+ */
+ SSLSession getSSLSession();
+
+ /**
+ * Opens this connection according to the given route.
+ *
+ * @param route the route along which to open. It will be opened to
+ * the first proxy if present, or directly to the target.
+ * @param context the context for opening this connection
+ * @param params the parameters for opening this connection
+ *
+ * @throws IOException in case of a problem
+ */
+ void open(HttpRoute route, HttpContext context, HttpParams params)
+ throws IOException;
+
+ /**
+ * Indicates that a tunnel to the target has been established.
+ * The route is the one previously passed to {@link #open open}.
+ * Subsequently, {@link #layerProtocol layerProtocol} can be called
+ * to layer the TLS/SSL protocol on top of the tunnelled connection.
+ * <br/>
+ * <b>Note:</b> In HttpClient 3, a call to the corresponding method
+ * would automatically trigger the layering of the TLS/SSL protocol.
+ * This is not the case anymore, you can establish a tunnel without
+ * layering a new protocol over the connection.
+ *
+ * @param secure <code>true</code> if the tunnel should be considered
+ * secure, <code>false</code> otherwise
+ * @param params the parameters for tunnelling this connection
+ *
+ * @throws IOException in case of a problem
+ */
+ void tunnelTarget(boolean secure, HttpParams params)
+ throws IOException;
+
+ /**
+ * Indicates that a tunnel to an intermediate proxy has been established.
+ * This is used exclusively for so-called <i>proxy chains</i>, where
+ * a request has to pass through multiple proxies before reaching the
+ * target. In that case, all proxies but the last need to be tunnelled
+ * when establishing the connection. Tunnelling of the last proxy to the
+ * target is optional and would be indicated via {@link #tunnelTarget}.
+ *
+ * @param next the proxy to which the tunnel was established.
+ * This is <i>not</i> the proxy <i>through</i> which
+ * the tunnel was established, but the new end point
+ * of the tunnel. The tunnel does <i>not</i> yet
+ * reach to the target, use {@link #tunnelTarget}
+ * to indicate an end-to-end tunnel.
+ * @param secure <code>true</code> if the connection should be
+ * considered secure, <code>false</code> otherwise
+ * @param params the parameters for tunnelling this connection
+ *
+ * @throws IOException in case of a problem
+ */
+ void tunnelProxy(HttpHost next, boolean secure, HttpParams params)
+ throws IOException;
+
+ /**
+ * Layers a new protocol on top of a {@link #tunnelTarget tunnelled}
+ * connection. This is typically used to create a TLS/SSL connection
+ * through a proxy.
+ * The route is the one previously passed to {@link #open open}.
+ * It is not guaranteed that the layered connection is
+ * {@link #isSecure secure}.
+ *
+ * @param context the context for layering on top of this connection
+ * @param params the parameters for layering on top of this connection
+ *
+ * @throws IOException in case of a problem
+ */
+ void layerProtocol(HttpContext context, HttpParams params)
+ throws IOException;
+
+ /**
+ * Marks this connection as being in a reusable communication state.
+ * The checkpoints for reuseable communication states (in the absence
+ * of pipelining) are before sending a request and after receiving
+ * the response in its entirety.
+ * The connection will automatically clear the checkpoint when
+ * used for communication. A call to this method indicates that
+ * the next checkpoint has been reached.
+ * <br/>
+ * A reusable communication state is necessary but not sufficient
+ * for the connection to be reused.
+ * A {@link #getRoute route} mismatch, the connection being closed,
+ * or other circumstances might prevent reuse.
+ */
+ void markReusable();
+
+ /**
+ * Marks this connection as not being in a reusable state.
+ * This can be used immediately before releasing this connection
+ * to prevent its reuse. Reasons for preventing reuse include
+ * error conditions and the evaluation of a
+ * {@link ch.boye.httpclientandroidlib.ConnectionReuseStrategy reuse strategy}.
+ * <br/>
+ * <b>Note:</b>
+ * It is <i>not</i> necessary to call here before writing to
+ * or reading from this connection. Communication attempts will
+ * automatically unmark the state as non-reusable. It can then
+ * be switched back using {@link #markReusable markReusable}.
+ */
+ void unmarkReusable();
+
+ /**
+ * Indicates whether this connection is in a reusable communication state.
+ * See {@link #markReusable markReusable} and
+ * {@link #unmarkReusable unmarkReusable} for details.
+ *
+ * @return <code>true</code> if this connection is marked as being in
+ * a reusable communication state,
+ * <code>false</code> otherwise
+ */
+ boolean isMarkedReusable();
+
+ /**
+ * Assigns a state object to this connection. Connection managers may make
+ * use of the connection state when allocating persistent connections.
+ *
+ * @param state The state object
+ */
+ void setState(Object state);
+
+ /**
+ * Returns the state object associated with this connection.
+ *
+ * @return The state object
+ */
+ Object getState();
+
+ /**
+ * Sets the duration that this connection can remain idle before it is
+ * reused. The connection should not be used again if this time elapses. The
+ * idle duration must be reset after each request sent over this connection.
+ * The elapsed time starts counting when the connection is released, which
+ * is typically after the headers (and any response body, if present) is
+ * fully consumed.
+ */
+ void setIdleDuration(long duration, TimeUnit unit);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedHttpClientConnection.java
new file mode 100644
index 000000000..4195d59b7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedHttpClientConnection.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import javax.net.ssl.SSLSession;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpInetConnection;
+
+/**
+ * Represents a managed connection whose state and life cycle is managed by
+ * a connection manager. This interface extends {@link HttpClientConnection}
+ * with methods to bind the connection to an arbitrary socket and
+ * to obtain SSL session details.
+ *
+ * @since 4.3
+ */
+public interface ManagedHttpClientConnection extends HttpClientConnection, HttpInetConnection {
+
+ /**
+ * Returns connection ID which is expected to be unique
+ * for the life span of the connection manager.
+ */
+ String getId();
+
+ /**
+ * Binds this connection to the given socket. The connection
+ * is considered open if it is bound and the underlying socket
+ * is connection to a remote host.
+ *
+ * @param socket the socket to bind the connection to.
+ * @throws IOException
+ */
+ void bind(Socket socket) throws IOException;
+
+ /**
+ * Returns the underlying socket.
+ */
+ Socket getSocket();
+
+ /**
+ * Obtains the SSL session of the underlying connection, if any.
+ * If this connection is open, and the underlying socket is an
+ * {@link javax.net.ssl.SSLSocket SSLSocket}, the SSL session of
+ * that socket is obtained. This is a potentially blocking operation.
+ *
+ * @return the underlying SSL session if available,
+ * <code>null</code> otherwise
+ */
+ SSLSession getSSLSession();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/MultihomePlainSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/MultihomePlainSocketFactory.java
new file mode 100644
index 000000000..c4c34f769
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/MultihomePlainSocketFactory.java
@@ -0,0 +1,173 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.scheme.SocketFactory;
+import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Socket factory that implements a simple multi-home fail-over on connect failure,
+ * provided the same hostname resolves to multiple {@link InetAddress}es. Please note
+ * the {@link #connectSocket(Socket, String, int, InetAddress, int, HttpParams)}
+ * method cannot be reliably interrupted by closing the socket returned by the
+ * {@link #createSocket()} method.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) Do not use. For multihome support socket factories must implement
+ * {@link ch.boye.httpclientandroidlib.conn.scheme.SchemeSocketFactory} interface.
+ */
+@Deprecated
+@Immutable
+public final class MultihomePlainSocketFactory implements SocketFactory {
+
+ /**
+ * The factory singleton.
+ */
+ private static final
+ MultihomePlainSocketFactory DEFAULT_FACTORY = new MultihomePlainSocketFactory();
+
+ /**
+ * Gets the singleton instance of this class.
+ * @return the one and only plain socket factory
+ */
+ public static MultihomePlainSocketFactory getSocketFactory() {
+ return DEFAULT_FACTORY;
+ }
+
+ /**
+ * Restricted default constructor.
+ */
+ private MultihomePlainSocketFactory() {
+ super();
+ }
+
+
+ // non-javadoc, see interface ch.boye.httpclientandroidlib.conn.SocketFactory
+ public Socket createSocket() {
+ return new Socket();
+ }
+
+ /**
+ * Attempts to connects the socket to any of the {@link InetAddress}es the
+ * given host name resolves to. If connection to all addresses fail, the
+ * last I/O exception is propagated to the caller.
+ *
+ * @param socket socket to connect to any of the given addresses
+ * @param host Host name to connect to
+ * @param port the port to connect to
+ * @param localAddress local address
+ * @param localPort local port
+ * @param params HTTP parameters
+ *
+ * @throws IOException if an error occurs during the connection
+ * @throws SocketTimeoutException if timeout expires before connecting
+ */
+ public Socket connectSocket(final Socket socket, final String host, final int port,
+ final InetAddress localAddress, final int localPort,
+ final HttpParams params)
+ throws IOException {
+ Args.notNull(host, "Target host");
+ Args.notNull(params, "HTTP parameters");
+
+ Socket sock = socket;
+ if (sock == null) {
+ sock = createSocket();
+ }
+
+ if ((localAddress != null) || (localPort > 0)) {
+ final InetSocketAddress isa = new InetSocketAddress(localAddress,
+ localPort > 0 ? localPort : 0);
+ sock.bind(isa);
+ }
+
+ final int timeout = HttpConnectionParams.getConnectionTimeout(params);
+
+ final InetAddress[] inetadrs = InetAddress.getAllByName(host);
+ final List<InetAddress> addresses = new ArrayList<InetAddress>(inetadrs.length);
+ addresses.addAll(Arrays.asList(inetadrs));
+ Collections.shuffle(addresses);
+
+ IOException lastEx = null;
+ for (final InetAddress remoteAddress: addresses) {
+ try {
+ sock.connect(new InetSocketAddress(remoteAddress, port), timeout);
+ break;
+ } catch (final SocketTimeoutException ex) {
+ throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out");
+ } catch (final IOException ex) {
+ // create new socket
+ sock = new Socket();
+ // keep the last exception and retry
+ lastEx = ex;
+ }
+ }
+ if (lastEx != null) {
+ throw lastEx;
+ }
+ return sock;
+ } // connectSocket
+
+
+ /**
+ * Checks whether a socket connection is secure.
+ * This factory creates plain socket connections
+ * which are not considered secure.
+ *
+ * @param sock the connected socket
+ *
+ * @return <code>false</code>
+ *
+ * @throws IllegalArgumentException if the argument is invalid
+ */
+ public final boolean isSecure(final Socket sock)
+ throws IllegalArgumentException {
+
+ Args.notNull(sock, "Socket");
+ // This check is performed last since it calls a method implemented
+ // by the argument object. getClass() is final in java.lang.Object.
+ Asserts.check(!sock.isClosed(), "Socket is closed");
+ return false;
+
+ } // isSecure
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/OperatedClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/OperatedClientConnection.java
new file mode 100644
index 000000000..3f8df0591
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/OperatedClientConnection.java
@@ -0,0 +1,155 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpInetConnection;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * A client-side connection that relies on outside logic to connect sockets to the
+ * appropriate hosts. It can be operated directly by an application, or through an
+ * {@link ClientConnectionOperator operator}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}.
+ */
+@Deprecated
+public interface OperatedClientConnection extends HttpClientConnection, HttpInetConnection {
+
+ /**
+ * Obtains the target host for this connection.
+ * If the connection is to a proxy but not tunnelled, this is
+ * the proxy. If the connection is tunnelled through a proxy,
+ * this is the target of the tunnel.
+ * <br/>
+ * The return value is well-defined only while the connection is open.
+ * It may change even while the connection is open,
+ * because of an {@link #update update}.
+ *
+ * @return the host to which this connection is opened
+ */
+ HttpHost getTargetHost();
+
+ /**
+ * Indicates whether this connection is secure.
+ * The return value is well-defined only while the connection is open.
+ * It may change even while the connection is open,
+ * because of an {@link #update update}.
+ *
+ * @return <code>true</code> if this connection is secure,
+ * <code>false</code> otherwise
+ */
+ boolean isSecure();
+
+ /**
+ * Obtains the socket for this connection.
+ * The return value is well-defined only while the connection is open.
+ * It may change even while the connection is open,
+ * because of an {@link #update update}.
+ *
+ * @return the socket for communicating with the
+ * {@link #getTargetHost target host}
+ */
+ Socket getSocket();
+
+ /**
+ * Signals that this connection is in the process of being open.
+ * <p>
+ * By calling this method, the connection can be re-initialized
+ * with a new Socket instance before {@link #openCompleted} is called.
+ * This enabled the connection to close that socket if
+ * {@link ch.boye.httpclientandroidlib.HttpConnection#shutdown shutdown}
+ * is called before it is fully open. Closing an unconnected socket
+ * will interrupt a thread that is blocked on the connect.
+ * Otherwise, that thread will either time out on the connect,
+ * or it returns successfully and then opens this connection
+ * which was just shut down.
+ * <p>
+ * This method can be called multiple times if the connection
+ * is layered over another protocol. <b>Note:</b> This method
+ * will <i>not</i> close the previously used socket. It is
+ * the caller's responsibility to close that socket if it is
+ * no longer required.
+ * <p>
+ * The caller must invoke {@link #openCompleted} in order to complete
+ * the process.
+ *
+ * @param sock the unconnected socket which is about to
+ * be connected.
+ * @param target the target host of this connection
+ */
+ void opening(Socket sock, HttpHost target)
+ throws IOException;
+
+ /**
+ * Signals that the connection has been successfully open.
+ * An attempt to call this method on an open connection will cause
+ * an exception.
+ *
+ * @param secure <code>true</code> if this connection is secure, for
+ * example if an <code>SSLSocket</code> is used, or
+ * <code>false</code> if it is not secure
+ * @param params parameters for this connection. The parameters will
+ * be used when creating dependent objects, for example
+ * to determine buffer sizes.
+ */
+ void openCompleted(boolean secure, HttpParams params)
+ throws IOException;
+
+ /**
+ * Updates this connection.
+ * A connection can be updated only while it is open.
+ * Updates are used for example when a tunnel has been established,
+ * or when a TLS/SSL connection has been layered on top of a plain
+ * socket connection.
+ * <br/>
+ * <b>Note:</b> Updating the connection will <i>not</i> close the
+ * previously used socket. It is the caller's responsibility to close
+ * that socket if it is no longer required.
+ *
+ * @param sock the new socket for communicating with the target host,
+ * or <code>null</code> to continue using the old socket.
+ * If <code>null</code> is passed, helper objects that
+ * depend on the socket should be re-used. In that case,
+ * some changes in the parameters will not take effect.
+ * @param target the new target host of this connection
+ * @param secure <code>true</code> if this connection is now secure,
+ * <code>false</code> if it is not secure
+ * @param params new parameters for this connection
+ */
+ void update(Socket sock, HttpHost target,
+ boolean secure, HttpParams params)
+ throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/SchemePortResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/SchemePortResolver.java
new file mode 100644
index 000000000..10df60f04
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/SchemePortResolver.java
@@ -0,0 +1,43 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+
+/**
+ * Strategy for default port resolution for protocol schemes.
+ *
+ * @since 4.3
+ */
+public interface SchemePortResolver {
+
+ /**
+ * Returns the actual port for the host based on the protocol scheme.
+ */
+ int resolve(HttpHost host) throws UnsupportedSchemeException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/UnsupportedSchemeException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/UnsupportedSchemeException.java
new file mode 100644
index 000000000..c8034191e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/UnsupportedSchemeException.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals failure to establish connection using an unknown protocol scheme.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class UnsupportedSchemeException extends IOException {
+
+ private static final long serialVersionUID = 3597127619218687636L;
+
+ /**
+ * Creates a UnsupportedSchemeException with the specified detail message.
+ */
+ public UnsupportedSchemeException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/package-info.java
new file mode 100644
index 000000000..6d83f5a8b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client connection management APIs.
+ */
+package ch.boye.httpclientandroidlib.conn;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionPNames.java
new file mode 100644
index 000000000..59246459f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionPNames.java
@@ -0,0 +1,64 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.params;
+
+/**
+ * Parameter names for HTTP client connections.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use custom {@link
+ * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation.
+ */
+@Deprecated
+public interface ConnConnectionPNames {
+
+ /**
+ * Defines the maximum number of ignorable lines before we expect
+ * a HTTP response's status line.
+ * <p>
+ * With HTTP/1.1 persistent connections, the problem arises that
+ * broken scripts could return a wrong Content-Length
+ * (there are more bytes sent than specified).
+ * Unfortunately, in some cases, this cannot be detected after the
+ * bad response, but only before the next one.
+ * So HttpClient must be able to skip those surplus lines this way.
+ * </p>
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * 0 disallows all garbage/empty lines before the status line.
+ * Use {@link java.lang.Integer#MAX_VALUE} for unlimited number.
+ * </p>
+ *
+ * @deprecated (4.1) Use custom {@link
+ * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation
+ */
+ @Deprecated
+ public static final String MAX_STATUS_LINE_GARBAGE = "http.connection.max-status-line-garbage";
+
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionParamBean.java
new file mode 100644
index 000000000..8c8b1b2dc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionParamBean.java
@@ -0,0 +1,59 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.params;
+
+import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate HTTP client connection parameters
+ * using Java Beans conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use custom {@link
+ * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation.
+ */
+@Deprecated
+public class ConnConnectionParamBean extends HttpAbstractParamBean {
+
+ public ConnConnectionParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ /**
+ * @deprecated (4.2) Use custom {@link
+ * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation
+ */
+ @Deprecated
+ public void setMaxStatusLineGarbage (final int maxStatusLineGarbage) {
+ params.setIntParameter(ConnConnectionPNames.MAX_STATUS_LINE_GARBAGE, maxStatusLineGarbage);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerPNames.java
new file mode 100644
index 000000000..16a79ca18
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerPNames.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.params;
+
+/**
+ * Parameter names for connection managers in HttpConn.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use configuration methods of the specific connection manager implementation.
+*/
+@Deprecated
+public interface ConnManagerPNames {
+
+ /**
+ * Defines the timeout in milliseconds used when retrieving an instance of
+ * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the
+ * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}.
+ * <p>
+ * This parameter expects a value of type {@link Long}.
+ */
+ public static final String TIMEOUT = "http.conn-manager.timeout";
+
+ /**
+ * Defines the maximum number of connections per route.
+ * This limit is interpreted by client connection managers
+ * and applies to individual manager instances.
+ * <p>
+ * This parameter expects a value of type {@link ConnPerRoute}.
+ * <p>
+ */
+ public static final String MAX_CONNECTIONS_PER_ROUTE = "http.conn-manager.max-per-route";
+
+ /**
+ * Defines the maximum number of connections in total.
+ * This limit is interpreted by client connection managers
+ * and applies to individual manager instances.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ */
+ public static final String MAX_TOTAL_CONNECTIONS = "http.conn-manager.max-total";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParamBean.java
new file mode 100644
index 000000000..735a25360
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParamBean.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.params;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate connection manager parameters
+ * using Java Beans conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use configuration methods of the specific connection manager implementation.
+ */
+@NotThreadSafe
+@Deprecated
+public class ConnManagerParamBean extends HttpAbstractParamBean {
+
+ public ConnManagerParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ public void setTimeout (final long timeout) {
+ params.setLongParameter(ConnManagerPNames.TIMEOUT, timeout);
+ }
+
+ public void setMaxTotalConnections (final int maxConnections) {
+ params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, maxConnections);
+ }
+
+ public void setConnectionsPerRoute(final ConnPerRouteBean connPerRoute) {
+ params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, connPerRoute);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParams.java
new file mode 100644
index 000000000..e6521134a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParams.java
@@ -0,0 +1,147 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.params;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * An adaptor for manipulating HTTP connection management
+ * parameters in {@link HttpParams}.
+ *
+ * @since 4.0
+ *
+ * @see ConnManagerPNames
+ *
+ * @deprecated (4.1) use configuration methods of the specific connection manager implementation.
+ */
+@Deprecated
+@Immutable
+public final class ConnManagerParams implements ConnManagerPNames {
+
+ /** The default maximum number of connections allowed overall */
+ public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20;
+
+ /**
+ * Returns the timeout in milliseconds used when retrieving a
+ * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the
+ * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}.
+ *
+ * @return timeout in milliseconds.
+ *
+ * @deprecated (4.1) use {@link
+ * ch.boye.httpclientandroidlib.params.HttpConnectionParams#getConnectionTimeout(HttpParams)}
+ */
+ @Deprecated
+ public static long getTimeout(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getLongParameter(TIMEOUT, 0);
+ }
+
+ /**
+ * Sets the timeout in milliseconds used when retrieving a
+ * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the
+ * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}.
+ *
+ * @param timeout the timeout in milliseconds
+ *
+ * @deprecated (4.1) use {@link
+ * ch.boye.httpclientandroidlib.params.HttpConnectionParams#setConnectionTimeout(HttpParams, int)}
+ */
+ @Deprecated
+ public static void setTimeout(final HttpParams params, final long timeout) {
+ Args.notNull(params, "HTTP parameters");
+ params.setLongParameter(TIMEOUT, timeout);
+ }
+
+ /** The default maximum number of connections allowed per host */
+ private static final ConnPerRoute DEFAULT_CONN_PER_ROUTE = new ConnPerRoute() {
+
+ public int getMaxForRoute(final HttpRoute route) {
+ return ConnPerRouteBean.DEFAULT_MAX_CONNECTIONS_PER_ROUTE;
+ }
+
+ };
+
+ /**
+ * Sets lookup interface for maximum number of connections allowed per route.
+ *
+ * @param params HTTP parameters
+ * @param connPerRoute lookup interface for maximum number of connections allowed
+ * per route
+ */
+ public static void setMaxConnectionsPerRoute(final HttpParams params,
+ final ConnPerRoute connPerRoute) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(MAX_CONNECTIONS_PER_ROUTE, connPerRoute);
+ }
+
+ /**
+ * Returns lookup interface for maximum number of connections allowed per route.
+ *
+ * @param params HTTP parameters
+ *
+ * @return lookup interface for maximum number of connections allowed per route.
+ */
+ public static ConnPerRoute getMaxConnectionsPerRoute(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ ConnPerRoute connPerRoute = (ConnPerRoute) params.getParameter(MAX_CONNECTIONS_PER_ROUTE);
+ if (connPerRoute == null) {
+ connPerRoute = DEFAULT_CONN_PER_ROUTE;
+ }
+ return connPerRoute;
+ }
+
+ /**
+ * Sets the maximum number of connections allowed.
+ *
+ * @param params HTTP parameters
+ * @param maxTotalConnections The maximum number of connections allowed.
+ */
+ public static void setMaxTotalConnections(
+ final HttpParams params,
+ final int maxTotalConnections) {
+ Args.notNull(params, "HTTP parameters");
+ params.setIntParameter(MAX_TOTAL_CONNECTIONS, maxTotalConnections);
+ }
+
+ /**
+ * Gets the maximum number of connections allowed.
+ *
+ * @param params HTTP parameters
+ *
+ * @return The maximum number of connections allowed.
+ */
+ public static int getMaxTotalConnections(
+ final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getIntParameter(MAX_TOTAL_CONNECTIONS, DEFAULT_MAX_TOTAL_CONNECTIONS);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRoute.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRoute.java
new file mode 100644
index 000000000..ebaad93cb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRoute.java
@@ -0,0 +1,46 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.params;
+
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+
+/**
+ * This interface is intended for looking up maximum number of connections
+ * allowed for a given route. This class can be used by pooling
+ * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager connection managers} for
+ * a fine-grained control of connections on a per route basis.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) no longer used.
+ */
+@Deprecated
+public interface ConnPerRoute {
+
+ int getMaxForRoute(HttpRoute route);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRouteBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRouteBean.java
new file mode 100644
index 000000000..6cc6da8ab
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRouteBean.java
@@ -0,0 +1,112 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.params;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * This class maintains a map of HTTP routes to maximum number of connections allowed
+ * for those routes. This class can be used by pooling
+ * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager connection managers} for
+ * a fine-grained control of connections on a per route basis.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.ConnPoolControl}
+ */
+@Deprecated
+@ThreadSafe
+public final class ConnPerRouteBean implements ConnPerRoute {
+
+ /** The default maximum number of connections allowed per host */
+ public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; // Per RFC 2616 sec 8.1.4
+
+ private final ConcurrentHashMap<HttpRoute, Integer> maxPerHostMap;
+
+ private volatile int defaultMax;
+
+ public ConnPerRouteBean(final int defaultMax) {
+ super();
+ this.maxPerHostMap = new ConcurrentHashMap<HttpRoute, Integer>();
+ setDefaultMaxPerRoute(defaultMax);
+ }
+
+ public ConnPerRouteBean() {
+ this(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
+ }
+
+ public int getDefaultMax() {
+ return this.defaultMax;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int getDefaultMaxPerRoute() {
+ return this.defaultMax;
+ }
+
+ public void setDefaultMaxPerRoute(final int max) {
+ Args.positive(max, "Defautl max per route");
+ this.defaultMax = max;
+ }
+
+ public void setMaxForRoute(final HttpRoute route, final int max) {
+ Args.notNull(route, "HTTP route");
+ Args.positive(max, "Max per route");
+ this.maxPerHostMap.put(route, Integer.valueOf(max));
+ }
+
+ public int getMaxForRoute(final HttpRoute route) {
+ Args.notNull(route, "HTTP route");
+ final Integer max = this.maxPerHostMap.get(route);
+ if (max != null) {
+ return max.intValue();
+ } else {
+ return this.defaultMax;
+ }
+ }
+
+ public void setMaxForRoutes(final Map<HttpRoute, Integer> map) {
+ if (map == null) {
+ return;
+ }
+ this.maxPerHostMap.clear();
+ this.maxPerHostMap.putAll(map);
+ }
+
+ @Override
+ public String toString() {
+ return this.maxPerHostMap.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRoutePNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRoutePNames.java
new file mode 100644
index 000000000..083216b14
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRoutePNames.java
@@ -0,0 +1,79 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.params;
+
+/**
+ * Parameter names for connection routing.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
+ */
+@Deprecated
+public interface ConnRoutePNames {
+
+ /**
+ * Parameter for the default proxy.
+ * The default value will be used by some
+ * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner HttpRoutePlanner}
+ * implementations, in particular the default implementation.
+ * <p>
+ * This parameter expects a value of type {@link ch.boye.httpclientandroidlib.HttpHost}.
+ * </p>
+ */
+ public static final String DEFAULT_PROXY = "http.route.default-proxy";
+
+ /**
+ * Parameter for the local address.
+ * On machines with multiple network interfaces, this parameter
+ * can be used to select the network interface from which the
+ * connection originates.
+ * It will be interpreted by the standard
+ * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner HttpRoutePlanner}
+ * implementations, in particular the default implementation.
+ * <p>
+ * This parameter expects a value of type {@link java.net.InetAddress}.
+ * </p>
+ */
+ public static final String LOCAL_ADDRESS = "http.route.local-address";
+
+ /**
+ * Parameter for an forced route.
+ * The forced route will be interpreted by the standard
+ * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner HttpRoutePlanner}
+ * implementations.
+ * Instead of computing a route, the given forced route will be
+ * returned, even if it points to the wrong target host.
+ * <p>
+ * This parameter expects a value of type
+ * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoute HttpRoute}.
+ * </p>
+ */
+ public static final String FORCED_ROUTE = "http.route.forced-route";
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParamBean.java
new file mode 100644
index 000000000..d3018ad0b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParamBean.java
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.params;
+
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate connection routing parameters
+ * using Java Beans conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
+ */
+@Deprecated
+@NotThreadSafe
+public class ConnRouteParamBean extends HttpAbstractParamBean {
+
+ public ConnRouteParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ /** @see ConnRoutePNames#DEFAULT_PROXY */
+ public void setDefaultProxy (final HttpHost defaultProxy) {
+ params.setParameter(ConnRoutePNames.DEFAULT_PROXY, defaultProxy);
+ }
+
+ /** @see ConnRoutePNames#LOCAL_ADDRESS */
+ public void setLocalAddress (final InetAddress address) {
+ params.setParameter(ConnRoutePNames.LOCAL_ADDRESS, address);
+ }
+
+ /** @see ConnRoutePNames#FORCED_ROUTE */
+ public void setForcedRoute (final HttpRoute route) {
+ params.setParameter(ConnRoutePNames.FORCED_ROUTE, route);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParams.java
new file mode 100644
index 000000000..241953dbd
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParams.java
@@ -0,0 +1,178 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.params;
+
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * An adaptor for manipulating HTTP routing parameters
+ * in {@link HttpParams}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}.
+ */
+@Deprecated
+@Immutable
+public class ConnRouteParams implements ConnRoutePNames {
+
+ /**
+ * A special value indicating "no host".
+ * This relies on a nonsense scheme name to avoid conflicts
+ * with actual hosts. Note that this is a <i>valid</i> host.
+ */
+ public static final HttpHost NO_HOST =
+ new HttpHost("127.0.0.255", 0, "no-host"); // Immutable
+
+ /**
+ * A special value indicating "no route".
+ * This is a route with {@link #NO_HOST} as the target.
+ */
+ public static final HttpRoute NO_ROUTE = new HttpRoute(NO_HOST); // Immutable
+
+ /** Disabled default constructor. */
+ private ConnRouteParams() {
+ // no body
+ }
+
+ /**
+ * Obtains the {@link ConnRoutePNames#DEFAULT_PROXY DEFAULT_PROXY}
+ * parameter value.
+ * {@link #NO_HOST} will be mapped to <code>null</code>,
+ * to allow unsetting in a hierarchy.
+ *
+ * @param params the parameters in which to look up
+ *
+ * @return the default proxy set in the argument parameters, or
+ * <code>null</code> if not set
+ */
+ public static HttpHost getDefaultProxy(final HttpParams params) {
+ Args.notNull(params, "Parameters");
+ HttpHost proxy = (HttpHost)
+ params.getParameter(DEFAULT_PROXY);
+ if ((proxy != null) && NO_HOST.equals(proxy)) {
+ // value is explicitly unset
+ proxy = null;
+ }
+ return proxy;
+ }
+
+ /**
+ * Sets the {@link ConnRoutePNames#DEFAULT_PROXY DEFAULT_PROXY}
+ * parameter value.
+ *
+ * @param params the parameters in which to set the value
+ * @param proxy the value to set, may be <code>null</code>.
+ * Note that {@link #NO_HOST} will be mapped to
+ * <code>null</code> by {@link #getDefaultProxy},
+ * to allow for explicit unsetting in hierarchies.
+ */
+ public static void setDefaultProxy(final HttpParams params,
+ final HttpHost proxy) {
+ Args.notNull(params, "Parameters");
+ params.setParameter(DEFAULT_PROXY, proxy);
+ }
+
+ /**
+ * Obtains the {@link ConnRoutePNames#FORCED_ROUTE FORCED_ROUTE}
+ * parameter value.
+ * {@link #NO_ROUTE} will be mapped to <code>null</code>,
+ * to allow unsetting in a hierarchy.
+ *
+ * @param params the parameters in which to look up
+ *
+ * @return the forced route set in the argument parameters, or
+ * <code>null</code> if not set
+ */
+ public static HttpRoute getForcedRoute(final HttpParams params) {
+ Args.notNull(params, "Parameters");
+ HttpRoute route = (HttpRoute)
+ params.getParameter(FORCED_ROUTE);
+ if ((route != null) && NO_ROUTE.equals(route)) {
+ // value is explicitly unset
+ route = null;
+ }
+ return route;
+ }
+
+ /**
+ * Sets the {@link ConnRoutePNames#FORCED_ROUTE FORCED_ROUTE}
+ * parameter value.
+ *
+ * @param params the parameters in which to set the value
+ * @param route the value to set, may be <code>null</code>.
+ * Note that {@link #NO_ROUTE} will be mapped to
+ * <code>null</code> by {@link #getForcedRoute},
+ * to allow for explicit unsetting in hierarchies.
+ */
+ public static void setForcedRoute(final HttpParams params,
+ final HttpRoute route) {
+ Args.notNull(params, "Parameters");
+ params.setParameter(FORCED_ROUTE, route);
+ }
+
+ /**
+ * Obtains the {@link ConnRoutePNames#LOCAL_ADDRESS LOCAL_ADDRESS}
+ * parameter value.
+ * There is no special value that would automatically be mapped to
+ * <code>null</code>. You can use the wildcard address (0.0.0.0 for IPv4,
+ * :: for IPv6) to override a specific local address in a hierarchy.
+ *
+ * @param params the parameters in which to look up
+ *
+ * @return the local address set in the argument parameters, or
+ * <code>null</code> if not set
+ */
+ public static InetAddress getLocalAddress(final HttpParams params) {
+ Args.notNull(params, "Parameters");
+ final InetAddress local = (InetAddress)
+ params.getParameter(LOCAL_ADDRESS);
+ // no explicit unsetting
+ return local;
+ }
+
+ /**
+ * Sets the {@link ConnRoutePNames#LOCAL_ADDRESS LOCAL_ADDRESS}
+ * parameter value.
+ *
+ * @param params the parameters in which to set the value
+ * @param local the value to set, may be <code>null</code>
+ */
+ public static void setLocalAddress(final HttpParams params,
+ final InetAddress local) {
+ Args.notNull(params, "Parameters");
+ params.setParameter(LOCAL_ADDRESS, local);
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/package-info.java
new file mode 100644
index 000000000..32b359e3e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Deprecated.
+ * @deprecated (4.3).
+ */
+package ch.boye.httpclientandroidlib.conn.params;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java
new file mode 100644
index 000000000..9c653eb3c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java
@@ -0,0 +1,181 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.routing;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic {@link HttpRouteDirector} implementation.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicRouteDirector implements HttpRouteDirector {
+
+ /**
+ * Provides the next step.
+ *
+ * @param plan the planned route
+ * @param fact the currently established route, or
+ * <code>null</code> if nothing is established
+ *
+ * @return one of the constants defined in this class, indicating
+ * either the next step to perform, or success, or failure.
+ * 0 is for success, a negative value for failure.
+ */
+ public int nextStep(final RouteInfo plan, final RouteInfo fact) {
+ Args.notNull(plan, "Planned route");
+
+ int step = UNREACHABLE;
+
+ if ((fact == null) || (fact.getHopCount() < 1)) {
+ step = firstStep(plan);
+ } else if (plan.getHopCount() > 1) {
+ step = proxiedStep(plan, fact);
+ } else {
+ step = directStep(plan, fact);
+ }
+
+ return step;
+
+ } // nextStep
+
+
+ /**
+ * Determines the first step to establish a route.
+ *
+ * @param plan the planned route
+ *
+ * @return the first step
+ */
+ protected int firstStep(final RouteInfo plan) {
+
+ return (plan.getHopCount() > 1) ?
+ CONNECT_PROXY : CONNECT_TARGET;
+ }
+
+
+ /**
+ * Determines the next step to establish a direct connection.
+ *
+ * @param plan the planned route
+ * @param fact the currently established route
+ *
+ * @return one of the constants defined in this class, indicating
+ * either the next step to perform, or success, or failure
+ */
+ protected int directStep(final RouteInfo plan, final RouteInfo fact) {
+
+ if (fact.getHopCount() > 1) {
+ return UNREACHABLE;
+ }
+ if (!plan.getTargetHost().equals(fact.getTargetHost()))
+ {
+ return UNREACHABLE;
+ // If the security is too low, we could now suggest to layer
+ // a secure protocol on the direct connection. Layering on direct
+ // connections has not been supported in HttpClient 3.x, we don't
+ // consider it here until there is a real-life use case for it.
+ }
+
+ // Should we tolerate if security is better than planned?
+ // (plan.isSecure() && !fact.isSecure())
+ if (plan.isSecure() != fact.isSecure()) {
+ return UNREACHABLE;
+ }
+
+ // Local address has to match only if the plan specifies one.
+ if ((plan.getLocalAddress() != null) &&
+ !plan.getLocalAddress().equals(fact.getLocalAddress())
+ ) {
+ return UNREACHABLE;
+ }
+
+ return COMPLETE;
+ }
+
+
+ /**
+ * Determines the next step to establish a connection via proxy.
+ *
+ * @param plan the planned route
+ * @param fact the currently established route
+ *
+ * @return one of the constants defined in this class, indicating
+ * either the next step to perform, or success, or failure
+ */
+ protected int proxiedStep(final RouteInfo plan, final RouteInfo fact) {
+
+ if (fact.getHopCount() <= 1) {
+ return UNREACHABLE;
+ }
+ if (!plan.getTargetHost().equals(fact.getTargetHost())) {
+ return UNREACHABLE;
+ }
+ final int phc = plan.getHopCount();
+ final int fhc = fact.getHopCount();
+ if (phc < fhc) {
+ return UNREACHABLE;
+ }
+
+ for (int i=0; i<fhc-1; i++) {
+ if (!plan.getHopTarget(i).equals(fact.getHopTarget(i))) {
+ return UNREACHABLE;
+ }
+ }
+ // now we know that the target matches and proxies so far are the same
+ if (phc > fhc)
+ {
+ return TUNNEL_PROXY; // need to extend the proxy chain
+ }
+
+ // proxy chain and target are the same, check tunnelling and layering
+ if ((fact.isTunnelled() && !plan.isTunnelled()) ||
+ (fact.isLayered() && !plan.isLayered())) {
+ return UNREACHABLE;
+ }
+
+ if (plan.isTunnelled() && !fact.isTunnelled()) {
+ return TUNNEL_TARGET;
+ }
+ if (plan.isLayered() && !fact.isLayered()) {
+ return LAYER_PROTOCOL;
+ }
+
+ // tunnel and layering are the same, remains to check the security
+ // Should we tolerate if security is better than planned?
+ // (plan.isSecure() && !fact.isSecure())
+ if (plan.isSecure() != fact.isSecure()) {
+ return UNREACHABLE;
+ }
+
+ return COMPLETE;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java
new file mode 100644
index 000000000..7bf02d14c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java
@@ -0,0 +1,328 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.routing;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * The route for a request.
+ *
+ * @since 4.0
+ */
+@Immutable
+public final class HttpRoute implements RouteInfo, Cloneable {
+
+ /** The target host to connect to. */
+ private final HttpHost targetHost;
+
+ /**
+ * The local address to connect from.
+ * <code>null</code> indicates that the default should be used.
+ */
+ private final InetAddress localAddress;
+
+ /** The proxy servers, if any. Never null. */
+ private final List<HttpHost> proxyChain;
+
+ /** Whether the the route is tunnelled through the proxy. */
+ private final TunnelType tunnelled;
+
+ /** Whether the route is layered. */
+ private final LayerType layered;
+
+ /** Whether the route is (supposed to be) secure. */
+ private final boolean secure;
+
+ private HttpRoute(final HttpHost target, final InetAddress local, final List<HttpHost> proxies,
+ final boolean secure, final TunnelType tunnelled, final LayerType layered) {
+ Args.notNull(target, "Target host");
+ this.targetHost = target;
+ this.localAddress = local;
+ if (proxies != null && !proxies.isEmpty()) {
+ this.proxyChain = new ArrayList<HttpHost>(proxies);
+ } else {
+ this.proxyChain = null;
+ }
+ if (tunnelled == TunnelType.TUNNELLED) {
+ Args.check(this.proxyChain != null, "Proxy required if tunnelled");
+ }
+ this.secure = secure;
+ this.tunnelled = tunnelled != null ? tunnelled : TunnelType.PLAIN;
+ this.layered = layered != null ? layered : LayerType.PLAIN;
+ }
+
+ /**
+ * Creates a new route with all attributes specified explicitly.
+ *
+ * @param target the host to which to route
+ * @param local the local address to route from, or
+ * <code>null</code> for the default
+ * @param proxies the proxy chain to use, or
+ * <code>null</code> for a direct route
+ * @param secure <code>true</code> if the route is (to be) secure,
+ * <code>false</code> otherwise
+ * @param tunnelled the tunnel type of this route
+ * @param layered the layering type of this route
+ */
+ public HttpRoute(final HttpHost target, final InetAddress local, final HttpHost[] proxies,
+ final boolean secure, final TunnelType tunnelled, final LayerType layered) {
+ this(target, local, proxies != null ? Arrays.asList(proxies) : null,
+ secure, tunnelled, layered);
+ }
+
+ /**
+ * Creates a new route with at most one proxy.
+ *
+ * @param target the host to which to route
+ * @param local the local address to route from, or
+ * <code>null</code> for the default
+ * @param proxy the proxy to use, or
+ * <code>null</code> for a direct route
+ * @param secure <code>true</code> if the route is (to be) secure,
+ * <code>false</code> otherwise
+ * @param tunnelled <code>true</code> if the route is (to be) tunnelled
+ * via the proxy,
+ * <code>false</code> otherwise
+ * @param layered <code>true</code> if the route includes a
+ * layered protocol,
+ * <code>false</code> otherwise
+ */
+ public HttpRoute(final HttpHost target, final InetAddress local, final HttpHost proxy,
+ final boolean secure, final TunnelType tunnelled, final LayerType layered) {
+ this(target, local, proxy != null ? Collections.singletonList(proxy) : null,
+ secure, tunnelled, layered);
+ }
+
+ /**
+ * Creates a new direct route.
+ * That is a route without a proxy.
+ *
+ * @param target the host to which to route
+ * @param local the local address to route from, or
+ * <code>null</code> for the default
+ * @param secure <code>true</code> if the route is (to be) secure,
+ * <code>false</code> otherwise
+ */
+ public HttpRoute(final HttpHost target, final InetAddress local, final boolean secure) {
+ this(target, local, Collections.<HttpHost>emptyList(), secure,
+ TunnelType.PLAIN, LayerType.PLAIN);
+ }
+
+ /**
+ * Creates a new direct insecure route.
+ *
+ * @param target the host to which to route
+ */
+ public HttpRoute(final HttpHost target) {
+ this(target, null, Collections.<HttpHost>emptyList(), false,
+ TunnelType.PLAIN, LayerType.PLAIN);
+ }
+
+ /**
+ * Creates a new route through a proxy.
+ * When using this constructor, the <code>proxy</code> MUST be given.
+ * For convenience, it is assumed that a secure connection will be
+ * layered over a tunnel through the proxy.
+ *
+ * @param target the host to which to route
+ * @param local the local address to route from, or
+ * <code>null</code> for the default
+ * @param proxy the proxy to use
+ * @param secure <code>true</code> if the route is (to be) secure,
+ * <code>false</code> otherwise
+ */
+ public HttpRoute(final HttpHost target, final InetAddress local, final HttpHost proxy,
+ final boolean secure) {
+ this(target, local, Collections.singletonList(Args.notNull(proxy, "Proxy host")), secure,
+ secure ? TunnelType.TUNNELLED : TunnelType.PLAIN,
+ secure ? LayerType.LAYERED : LayerType.PLAIN);
+ }
+
+ /**
+ * Creates a new plain route through a proxy.
+ *
+ * @param target the host to which to route
+ * @param proxy the proxy to use
+ *
+ * @since 4.3
+ */
+ public HttpRoute(final HttpHost target, final HttpHost proxy) {
+ this(target, null, proxy, false);
+ }
+
+ public final HttpHost getTargetHost() {
+ return this.targetHost;
+ }
+
+ public final InetAddress getLocalAddress() {
+ return this.localAddress;
+ }
+
+ public final InetSocketAddress getLocalSocketAddress() {
+ return this.localAddress != null ? new InetSocketAddress(this.localAddress, 0) : null;
+ }
+
+ public final int getHopCount() {
+ return proxyChain != null ? proxyChain.size() + 1 : 1;
+ }
+
+ public final HttpHost getHopTarget(final int hop) {
+ Args.notNegative(hop, "Hop index");
+ final int hopcount = getHopCount();
+ Args.check(hop < hopcount, "Hop index exceeds tracked route length");
+ if (hop < hopcount - 1) {
+ return this.proxyChain.get(hop);
+ } else {
+ return this.targetHost;
+ }
+ }
+
+ public final HttpHost getProxyHost() {
+ return proxyChain != null && !this.proxyChain.isEmpty() ? this.proxyChain.get(0) : null;
+ }
+
+ public final TunnelType getTunnelType() {
+ return this.tunnelled;
+ }
+
+ public final boolean isTunnelled() {
+ return (this.tunnelled == TunnelType.TUNNELLED);
+ }
+
+ public final LayerType getLayerType() {
+ return this.layered;
+ }
+
+ public final boolean isLayered() {
+ return (this.layered == LayerType.LAYERED);
+ }
+
+ public final boolean isSecure() {
+ return this.secure;
+ }
+
+ /**
+ * Compares this route to another.
+ *
+ * @param obj the object to compare with
+ *
+ * @return <code>true</code> if the argument is the same route,
+ * <code>false</code>
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HttpRoute) {
+ final HttpRoute that = (HttpRoute) obj;
+ return
+ // Do the cheapest tests first
+ (this.secure == that.secure) &&
+ (this.tunnelled == that.tunnelled) &&
+ (this.layered == that.layered) &&
+ LangUtils.equals(this.targetHost, that.targetHost) &&
+ LangUtils.equals(this.localAddress, that.localAddress) &&
+ LangUtils.equals(this.proxyChain, that.proxyChain);
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Generates a hash code for this route.
+ *
+ * @return the hash code
+ */
+ @Override
+ public final int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.targetHost);
+ hash = LangUtils.hashCode(hash, this.localAddress);
+ if (this.proxyChain != null) {
+ for (final HttpHost element : this.proxyChain) {
+ hash = LangUtils.hashCode(hash, element);
+ }
+ }
+ hash = LangUtils.hashCode(hash, this.secure);
+ hash = LangUtils.hashCode(hash, this.tunnelled);
+ hash = LangUtils.hashCode(hash, this.layered);
+ return hash;
+ }
+
+ /**
+ * Obtains a description of this route.
+ *
+ * @return a human-readable representation of this route
+ */
+ @Override
+ public final String toString() {
+ final StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
+ if (this.localAddress != null) {
+ cab.append(this.localAddress);
+ cab.append("->");
+ }
+ cab.append('{');
+ if (this.tunnelled == TunnelType.TUNNELLED) {
+ cab.append('t');
+ }
+ if (this.layered == LayerType.LAYERED) {
+ cab.append('l');
+ }
+ if (this.secure) {
+ cab.append('s');
+ }
+ cab.append("}->");
+ if (this.proxyChain != null) {
+ for (final HttpHost aProxyChain : this.proxyChain) {
+ cab.append(aProxyChain);
+ cab.append("->");
+ }
+ }
+ cab.append(this.targetHost);
+ return cab.toString();
+ }
+
+ // default implementation of clone() is sufficient
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java
new file mode 100644
index 000000000..f8b774603
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.routing;
+
+/**
+ * Provides directions on establishing a route.
+ * Implementations of this interface compare a planned route with
+ * a tracked route and indicate the next step required.
+ *
+ * @since 4.0
+ */
+public interface HttpRouteDirector {
+
+ /** Indicates that the route can not be established at all. */
+ public final static int UNREACHABLE = -1;
+
+ /** Indicates that the route is complete. */
+ public final static int COMPLETE = 0;
+
+ /** Step: open connection to target. */
+ public final static int CONNECT_TARGET = 1;
+
+ /** Step: open connection to proxy. */
+ public final static int CONNECT_PROXY = 2;
+
+ /** Step: tunnel through proxy to target. */
+ public final static int TUNNEL_TARGET = 3;
+
+ /** Step: tunnel through proxy to other proxy. */
+ public final static int TUNNEL_PROXY = 4;
+
+ /** Step: layer protocol (over tunnel). */
+ public final static int LAYER_PROTOCOL = 5;
+
+
+ /**
+ * Provides the next step.
+ *
+ * @param plan the planned route
+ * @param fact the currently established route, or
+ * <code>null</code> if nothing is established
+ *
+ * @return one of the constants defined in this interface, indicating
+ * either the next step to perform, or success, or failure.
+ * 0 is for success, a negative value for failure.
+ */
+ public int nextStep(RouteInfo plan, RouteInfo fact);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java
new file mode 100644
index 000000000..9e8ba19d3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.routing;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Encapsulates logic to compute a {@link HttpRoute} to a target host.
+ * Implementations may for example be based on parameters, or on the
+ * standard Java system properties.
+ * <p/>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 4.0
+ */
+public interface HttpRoutePlanner {
+
+ /**
+ * Determines the route for a request.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param context the context to use for the subsequent execution.
+ * Implementations may accept <code>null</code>.
+ *
+ * @return the route that the request should take
+ *
+ * @throws HttpException in case of a problem
+ */
+ public HttpRoute determineRoute(HttpHost target,
+ HttpRequest request,
+ HttpContext context) throws HttpException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java
new file mode 100644
index 000000000..0784b7894
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java
@@ -0,0 +1,161 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.routing;
+
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+
+/**
+ * Read-only interface for route information.
+ *
+ * @since 4.0
+ */
+public interface RouteInfo {
+
+ /**
+ * The tunnelling type of a route.
+ * Plain routes are established by connecting to the target or
+ * the first proxy.
+ * Tunnelled routes are established by connecting to the first proxy
+ * and tunnelling through all proxies to the target.
+ * Routes without a proxy cannot be tunnelled.
+ */
+ public enum TunnelType { PLAIN, TUNNELLED }
+
+ /**
+ * The layering type of a route.
+ * Plain routes are established by connecting or tunnelling.
+ * Layered routes are established by layering a protocol such as TLS/SSL
+ * over an existing connection.
+ * Protocols can only be layered over a tunnel to the target, or
+ * or over a direct connection without proxies.
+ * <br/>
+ * Layering a protocol
+ * over a direct connection makes little sense, since the connection
+ * could be established with the new protocol in the first place.
+ * But we don't want to exclude that use case.
+ */
+ public enum LayerType { PLAIN, LAYERED }
+
+ /**
+ * Obtains the target host.
+ *
+ * @return the target host
+ */
+ HttpHost getTargetHost();
+
+ /**
+ * Obtains the local address to connect from.
+ *
+ * @return the local address,
+ * or <code>null</code>
+ */
+ InetAddress getLocalAddress();
+
+ /**
+ * Obtains the number of hops in this route.
+ * A direct route has one hop. A route through a proxy has two hops.
+ * A route through a chain of <i>n</i> proxies has <i>n+1</i> hops.
+ *
+ * @return the number of hops in this route
+ */
+ int getHopCount();
+
+ /**
+ * Obtains the target of a hop in this route.
+ * The target of the last hop is the {@link #getTargetHost target host},
+ * the target of previous hops is the respective proxy in the chain.
+ * For a route through exactly one proxy, target of hop 0 is the proxy
+ * and target of hop 1 is the target host.
+ *
+ * @param hop index of the hop for which to get the target,
+ * 0 for first
+ *
+ * @return the target of the given hop
+ *
+ * @throws IllegalArgumentException
+ * if the argument is negative or not less than
+ * {@link #getHopCount getHopCount()}
+ */
+ HttpHost getHopTarget(int hop);
+
+ /**
+ * Obtains the first proxy host.
+ *
+ * @return the first proxy in the proxy chain, or
+ * <code>null</code> if this route is direct
+ */
+ HttpHost getProxyHost();
+
+ /**
+ * Obtains the tunnel type of this route.
+ * If there is a proxy chain, only end-to-end tunnels are considered.
+ *
+ * @return the tunnelling type
+ */
+ TunnelType getTunnelType();
+
+ /**
+ * Checks whether this route is tunnelled through a proxy.
+ * If there is a proxy chain, only end-to-end tunnels are considered.
+ *
+ * @return <code>true</code> if tunnelled end-to-end through at least
+ * one proxy,
+ * <code>false</code> otherwise
+ */
+ boolean isTunnelled();
+
+ /**
+ * Obtains the layering type of this route.
+ * In the presence of proxies, only layering over an end-to-end tunnel
+ * is considered.
+ *
+ * @return the layering type
+ */
+ LayerType getLayerType();
+
+ /**
+ * Checks whether this route includes a layered protocol.
+ * In the presence of proxies, only layering over an end-to-end tunnel
+ * is considered.
+ *
+ * @return <code>true</code> if layered,
+ * <code>false</code> otherwise
+ */
+ boolean isLayered();
+
+ /**
+ * Checks whether this route is secure.
+ *
+ * @return <code>true</code> if secure,
+ * <code>false</code> otherwise
+ */
+ boolean isSecure();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java
new file mode 100644
index 000000000..9a900319c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java
@@ -0,0 +1,366 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.routing;
+
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Helps tracking the steps in establishing a route.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public final class RouteTracker implements RouteInfo, Cloneable {
+
+ /** The target host to connect to. */
+ private final HttpHost targetHost;
+
+ /**
+ * The local address to connect from.
+ * <code>null</code> indicates that the default should be used.
+ */
+ private final InetAddress localAddress;
+
+ // the attributes above are fixed at construction time
+ // now follow attributes that indicate the established route
+
+ /** Whether the first hop of the route is established. */
+ private boolean connected;
+
+ /** The proxy chain, if any. */
+ private HttpHost[] proxyChain;
+
+ /** Whether the the route is tunnelled end-to-end through proxies. */
+ private TunnelType tunnelled;
+
+ /** Whether the route is layered over a tunnel. */
+ private LayerType layered;
+
+ /** Whether the route is secure. */
+ private boolean secure;
+
+ /**
+ * Creates a new route tracker.
+ * The target and origin need to be specified at creation time.
+ *
+ * @param target the host to which to route
+ * @param local the local address to route from, or
+ * <code>null</code> for the default
+ */
+ public RouteTracker(final HttpHost target, final InetAddress local) {
+ Args.notNull(target, "Target host");
+ this.targetHost = target;
+ this.localAddress = local;
+ this.tunnelled = TunnelType.PLAIN;
+ this.layered = LayerType.PLAIN;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void reset() {
+ this.connected = false;
+ this.proxyChain = null;
+ this.tunnelled = TunnelType.PLAIN;
+ this.layered = LayerType.PLAIN;
+ this.secure = false;
+ }
+
+ /**
+ * Creates a new tracker for the given route.
+ * Only target and origin are taken from the route,
+ * everything else remains to be tracked.
+ *
+ * @param route the route to track
+ */
+ public RouteTracker(final HttpRoute route) {
+ this(route.getTargetHost(), route.getLocalAddress());
+ }
+
+ /**
+ * Tracks connecting to the target.
+ *
+ * @param secure <code>true</code> if the route is secure,
+ * <code>false</code> otherwise
+ */
+ public final void connectTarget(final boolean secure) {
+ Asserts.check(!this.connected, "Already connected");
+ this.connected = true;
+ this.secure = secure;
+ }
+
+ /**
+ * Tracks connecting to the first proxy.
+ *
+ * @param proxy the proxy connected to
+ * @param secure <code>true</code> if the route is secure,
+ * <code>false</code> otherwise
+ */
+ public final void connectProxy(final HttpHost proxy, final boolean secure) {
+ Args.notNull(proxy, "Proxy host");
+ Asserts.check(!this.connected, "Already connected");
+ this.connected = true;
+ this.proxyChain = new HttpHost[]{ proxy };
+ this.secure = secure;
+ }
+
+ /**
+ * Tracks tunnelling to the target.
+ *
+ * @param secure <code>true</code> if the route is secure,
+ * <code>false</code> otherwise
+ */
+ public final void tunnelTarget(final boolean secure) {
+ Asserts.check(this.connected, "No tunnel unless connected");
+ Asserts.notNull(this.proxyChain, "No tunnel without proxy");
+ this.tunnelled = TunnelType.TUNNELLED;
+ this.secure = secure;
+ }
+
+ /**
+ * Tracks tunnelling to a proxy in a proxy chain.
+ * This will extend the tracked proxy chain, but it does not mark
+ * the route as tunnelled. Only end-to-end tunnels are considered there.
+ *
+ * @param proxy the proxy tunnelled to
+ * @param secure <code>true</code> if the route is secure,
+ * <code>false</code> otherwise
+ */
+ public final void tunnelProxy(final HttpHost proxy, final boolean secure) {
+ Args.notNull(proxy, "Proxy host");
+ Asserts.check(this.connected, "No tunnel unless connected");
+ Asserts.notNull(this.proxyChain, "No tunnel without proxy");
+ // prepare an extended proxy chain
+ final HttpHost[] proxies = new HttpHost[this.proxyChain.length+1];
+ System.arraycopy(this.proxyChain, 0,
+ proxies, 0, this.proxyChain.length);
+ proxies[proxies.length-1] = proxy;
+
+ this.proxyChain = proxies;
+ this.secure = secure;
+ }
+
+ /**
+ * Tracks layering a protocol.
+ *
+ * @param secure <code>true</code> if the route is secure,
+ * <code>false</code> otherwise
+ */
+ public final void layerProtocol(final boolean secure) {
+ // it is possible to layer a protocol over a direct connection,
+ // although this case is probably not considered elsewhere
+ Asserts.check(this.connected, "No layered protocol unless connected");
+ this.layered = LayerType.LAYERED;
+ this.secure = secure;
+ }
+
+ public final HttpHost getTargetHost() {
+ return this.targetHost;
+ }
+
+ public final InetAddress getLocalAddress() {
+ return this.localAddress;
+ }
+
+ public final int getHopCount() {
+ int hops = 0;
+ if (this.connected) {
+ if (proxyChain == null) {
+ hops = 1;
+ } else {
+ hops = proxyChain.length + 1;
+ }
+ }
+ return hops;
+ }
+
+ public final HttpHost getHopTarget(final int hop) {
+ Args.notNegative(hop, "Hop index");
+ final int hopcount = getHopCount();
+ Args.check(hop < hopcount, "Hop index exceeds tracked route length");
+ HttpHost result = null;
+ if (hop < hopcount-1) {
+ result = this.proxyChain[hop];
+ } else {
+ result = this.targetHost;
+ }
+
+ return result;
+ }
+
+ public final HttpHost getProxyHost() {
+ return (this.proxyChain == null) ? null : this.proxyChain[0];
+ }
+
+ public final boolean isConnected() {
+ return this.connected;
+ }
+
+ public final TunnelType getTunnelType() {
+ return this.tunnelled;
+ }
+
+ public final boolean isTunnelled() {
+ return (this.tunnelled == TunnelType.TUNNELLED);
+ }
+
+ public final LayerType getLayerType() {
+ return this.layered;
+ }
+
+ public final boolean isLayered() {
+ return (this.layered == LayerType.LAYERED);
+ }
+
+ public final boolean isSecure() {
+ return this.secure;
+ }
+
+ /**
+ * Obtains the tracked route.
+ * If a route has been tracked, it is {@link #isConnected connected}.
+ * If not connected, nothing has been tracked so far.
+ *
+ * @return the tracked route, or
+ * <code>null</code> if nothing has been tracked so far
+ */
+ public final HttpRoute toRoute() {
+ return !this.connected ?
+ null : new HttpRoute(this.targetHost, this.localAddress,
+ this.proxyChain, this.secure,
+ this.tunnelled, this.layered);
+ }
+
+ /**
+ * Compares this tracked route to another.
+ *
+ * @param o the object to compare with
+ *
+ * @return <code>true</code> if the argument is the same tracked route,
+ * <code>false</code>
+ */
+ @Override
+ public final boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof RouteTracker)) {
+ return false;
+ }
+
+ final RouteTracker that = (RouteTracker) o;
+ return
+ // Do the cheapest checks first
+ (this.connected == that.connected) &&
+ (this.secure == that.secure) &&
+ (this.tunnelled == that.tunnelled) &&
+ (this.layered == that.layered) &&
+ LangUtils.equals(this.targetHost, that.targetHost) &&
+ LangUtils.equals(this.localAddress, that.localAddress) &&
+ LangUtils.equals(this.proxyChain, that.proxyChain);
+ }
+
+ /**
+ * Generates a hash code for this tracked route.
+ * Route trackers are modifiable and should therefore not be used
+ * as lookup keys. Use {@link #toRoute toRoute} to obtain an
+ * unmodifiable representation of the tracked route.
+ *
+ * @return the hash code
+ */
+ @Override
+ public final int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.targetHost);
+ hash = LangUtils.hashCode(hash, this.localAddress);
+ if (this.proxyChain != null) {
+ for (final HttpHost element : this.proxyChain) {
+ hash = LangUtils.hashCode(hash, element);
+ }
+ }
+ hash = LangUtils.hashCode(hash, this.connected);
+ hash = LangUtils.hashCode(hash, this.secure);
+ hash = LangUtils.hashCode(hash, this.tunnelled);
+ hash = LangUtils.hashCode(hash, this.layered);
+ return hash;
+ }
+
+ /**
+ * Obtains a description of the tracked route.
+ *
+ * @return a human-readable representation of the tracked route
+ */
+ @Override
+ public final String toString() {
+ final StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
+
+ cab.append("RouteTracker[");
+ if (this.localAddress != null) {
+ cab.append(this.localAddress);
+ cab.append("->");
+ }
+ cab.append('{');
+ if (this.connected) {
+ cab.append('c');
+ }
+ if (this.tunnelled == TunnelType.TUNNELLED) {
+ cab.append('t');
+ }
+ if (this.layered == LayerType.LAYERED) {
+ cab.append('l');
+ }
+ if (this.secure) {
+ cab.append('s');
+ }
+ cab.append("}->");
+ if (this.proxyChain != null) {
+ for (final HttpHost element : this.proxyChain) {
+ cab.append(element);
+ cab.append("->");
+ }
+ }
+ cab.append(this.targetHost);
+ cab.append(']');
+
+ return cab.toString();
+ }
+
+
+ // default implementation of clone() is sufficient
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java
new file mode 100644
index 000000000..ddd6b8ae8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client connection routing APIs.
+ */
+package ch.boye.httpclientandroidlib.conn.routing;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/HostNameResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/HostNameResolver.java
new file mode 100644
index 000000000..8dcca6902
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/HostNameResolver.java
@@ -0,0 +1,52 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetAddress;
+
+/**
+ * Hostname to IP address resolver.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) Do not use
+ */
+@Deprecated
+public interface HostNameResolver {
+
+ /**
+ * Resolves given hostname to its IP address
+ *
+ * @param hostname the hostname.
+ * @return IP address.
+ * @throws IOException
+ */
+ InetAddress resolve (String hostname) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java
new file mode 100644
index 000000000..3833b2360
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java
@@ -0,0 +1,68 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ * Extended {@link SchemeSocketFactory} interface for layered sockets such as SSL/TLS.
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.2) use {@link SchemeLayeredSocketFactory}
+ */
+@Deprecated
+public interface LayeredSchemeSocketFactory extends SchemeSocketFactory {
+
+ /**
+ * Returns a socket connected to the given host that is layered over an
+ * existing socket. Used primarily for creating secure sockets through
+ * proxies.
+ *
+ * @param socket the existing socket
+ * @param target the name of the target host.
+ * @param port the port to connect to on the target host
+ * @param autoClose a flag for closing the underling socket when the created
+ * socket is closed
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ * @throws UnknownHostException if the IP address of the host cannot be
+ * determined
+ */
+ Socket createLayeredSocket(
+ Socket socket,
+ String target,
+ int port,
+ boolean autoClose
+ ) throws IOException, UnknownHostException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java
new file mode 100644
index 000000000..318e35f9c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ * A {@link SocketFactory SocketFactory} for layered sockets (SSL/TLS).
+ * See there for things to consider when implementing a socket factory.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use {@link SchemeSocketFactory}
+ */
+@Deprecated
+public interface LayeredSocketFactory extends SocketFactory {
+
+ /**
+ * Returns a socket connected to the given host that is layered over an
+ * existing socket. Used primarily for creating secure sockets through
+ * proxies.
+ *
+ * @param socket the existing socket
+ * @param host the host name/IP
+ * @param port the port on the host
+ * @param autoClose a flag for closing the underling socket when the created
+ * socket is closed
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ * @throws UnknownHostException if the IP address of the host cannot be
+ * determined
+ */
+ Socket createSocket(
+ Socket socket,
+ String host,
+ int port,
+ boolean autoClose
+ ) throws IOException, UnknownHostException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java
new file mode 100644
index 000000000..11ebd10cb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java
@@ -0,0 +1,53 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ * @deprecated (4.1) do not use
+ */
+@Deprecated
+class LayeredSocketFactoryAdaptor extends SocketFactoryAdaptor implements LayeredSocketFactory {
+
+ private final LayeredSchemeSocketFactory factory;
+
+ LayeredSocketFactoryAdaptor(final LayeredSchemeSocketFactory factory) {
+ super(factory);
+ this.factory = factory;
+ }
+
+ public Socket createSocket(
+ final Socket socket,
+ final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException {
+ return this.factory.createLayeredSocket(socket, host, port, autoClose);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/PlainSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/PlainSocketFactory.java
new file mode 100644
index 000000000..efa8f281b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/PlainSocketFactory.java
@@ -0,0 +1,160 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * The default class for creating plain (unencrypted) sockets.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.conn.socket.PlainConnectionSocketFactory}
+ */
+@Immutable
+@Deprecated
+public class PlainSocketFactory implements SocketFactory, SchemeSocketFactory {
+
+ private final HostNameResolver nameResolver;
+
+ /**
+ * Gets the default factory.
+ *
+ * @return the default factory
+ */
+ public static PlainSocketFactory getSocketFactory() {
+ return new PlainSocketFactory();
+ }
+
+ /**
+ * @deprecated (4.1) use {@link ch.boye.httpclientandroidlib.conn.DnsResolver}
+ */
+ @Deprecated
+ public PlainSocketFactory(final HostNameResolver nameResolver) {
+ super();
+ this.nameResolver = nameResolver;
+ }
+
+ public PlainSocketFactory() {
+ super();
+ this.nameResolver = null;
+ }
+
+ /**
+ * @param params Optional parameters. Parameters passed to this method will have no effect.
+ * This method will create a unconnected instance of {@link Socket} class
+ * using default constructor.
+ *
+ * @since 4.1
+ */
+ public Socket createSocket(final HttpParams params) {
+ return new Socket();
+ }
+
+ public Socket createSocket() {
+ return new Socket();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public Socket connectSocket(
+ final Socket socket,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final HttpParams params) throws IOException, ConnectTimeoutException {
+ Args.notNull(remoteAddress, "Remote address");
+ Args.notNull(params, "HTTP parameters");
+ Socket sock = socket;
+ if (sock == null) {
+ sock = createSocket();
+ }
+ if (localAddress != null) {
+ sock.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
+ sock.bind(localAddress);
+ }
+ final int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
+ final int soTimeout = HttpConnectionParams.getSoTimeout(params);
+
+ try {
+ sock.setSoTimeout(soTimeout);
+ sock.connect(remoteAddress, connTimeout);
+ } catch (final SocketTimeoutException ex) {
+ throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out");
+ }
+ return sock;
+ }
+
+ /**
+ * Checks whether a socket connection is secure.
+ * This factory creates plain socket connections
+ * which are not considered secure.
+ *
+ * @param sock the connected socket
+ *
+ * @return <code>false</code>
+ */
+ public final boolean isSecure(final Socket sock) {
+ return false;
+ }
+
+ /**
+ * @deprecated (4.1) Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}
+ */
+ @Deprecated
+ public Socket connectSocket(
+ final Socket socket,
+ final String host, final int port,
+ final InetAddress localAddress, final int localPort,
+ final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
+ InetSocketAddress local = null;
+ if (localAddress != null || localPort > 0) {
+ local = new InetSocketAddress(localAddress, localPort > 0 ? localPort : 0);
+ }
+ final InetAddress remoteAddress;
+ if (this.nameResolver != null) {
+ remoteAddress = this.nameResolver.resolve(host);
+ } else {
+ remoteAddress = InetAddress.getByName(host);
+ }
+ final InetSocketAddress remote = new InetSocketAddress(remoteAddress, port);
+ return connectSocket(socket, remote, local, params);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/Scheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/Scheme.java
new file mode 100644
index 000000000..93a44de35
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/Scheme.java
@@ -0,0 +1,260 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Encapsulates specifics of a protocol scheme such as "http" or "https". Schemes are identified
+ * by lowercase names. Supported schemes are typically collected in a {@link SchemeRegistry
+ * SchemeRegistry}.
+ * <p/>
+ * For example, to configure support for "https://" URLs, you could write code like the following:
+ * <pre>
+ * Scheme https = new Scheme("https", 443, new MySecureSocketFactory());
+ * SchemeRegistry registry = new SchemeRegistry();
+ * registry.register(https);
+ * </pre>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.conn.SchemePortResolver} for default port
+ * resolution and {@link ch.boye.httpclientandroidlib.config.Registry} for socket factory lookups.
+ */
+@Immutable
+@Deprecated
+public final class Scheme {
+
+ /** The name of this scheme, in lowercase. (e.g. http, https) */
+ private final String name;
+
+ /** The socket factory for this scheme */
+ private final SchemeSocketFactory socketFactory;
+
+ /** The default port for this scheme */
+ private final int defaultPort;
+
+ /** Indicates whether this scheme allows for layered connections */
+ private final boolean layered;
+
+ /** A string representation, for {@link #toString toString}. */
+ private String stringRep;
+ /*
+ * This is used to cache the result of the toString() method
+ * Since the method always generates the same value, there's no
+ * need to synchronize, and it does not affect immutability.
+ */
+
+ /**
+ * Creates a new scheme.
+ * Whether the created scheme allows for layered connections
+ * depends on the class of <code>factory</code>.
+ *
+ * @param name the scheme name, for example "http".
+ * The name will be converted to lowercase.
+ * @param port the default port for this scheme
+ * @param factory the factory for creating sockets for communication
+ * with this scheme
+ *
+ * @since 4.1
+ */
+ public Scheme(final String name, final int port, final SchemeSocketFactory factory) {
+ Args.notNull(name, "Scheme name");
+ Args.check(port > 0 && port <= 0xffff, "Port is invalid");
+ Args.notNull(factory, "Socket factory");
+ this.name = name.toLowerCase(Locale.ENGLISH);
+ this.defaultPort = port;
+ if (factory instanceof SchemeLayeredSocketFactory) {
+ this.layered = true;
+ this.socketFactory = factory;
+ } else if (factory instanceof LayeredSchemeSocketFactory) {
+ this.layered = true;
+ this.socketFactory = new SchemeLayeredSocketFactoryAdaptor2((LayeredSchemeSocketFactory) factory);
+ } else {
+ this.layered = false;
+ this.socketFactory = factory;
+ }
+ }
+
+ /**
+ * Creates a new scheme.
+ * Whether the created scheme allows for layered connections
+ * depends on the class of <code>factory</code>.
+ *
+ * @param name the scheme name, for example "http".
+ * The name will be converted to lowercase.
+ * @param factory the factory for creating sockets for communication
+ * with this scheme
+ * @param port the default port for this scheme
+ *
+ * @deprecated (4.1) Use {@link #Scheme(String, int, SchemeSocketFactory)}
+ */
+ @Deprecated
+ public Scheme(final String name,
+ final SocketFactory factory,
+ final int port) {
+
+ Args.notNull(name, "Scheme name");
+ Args.notNull(factory, "Socket factory");
+ Args.check(port > 0 && port <= 0xffff, "Port is invalid");
+
+ this.name = name.toLowerCase(Locale.ENGLISH);
+ if (factory instanceof LayeredSocketFactory) {
+ this.socketFactory = new SchemeLayeredSocketFactoryAdaptor(
+ (LayeredSocketFactory) factory);
+ this.layered = true;
+ } else {
+ this.socketFactory = new SchemeSocketFactoryAdaptor(factory);
+ this.layered = false;
+ }
+ this.defaultPort = port;
+ }
+
+ /**
+ * Obtains the default port.
+ *
+ * @return the default port for this scheme
+ */
+ public final int getDefaultPort() {
+ return defaultPort;
+ }
+
+
+ /**
+ * Obtains the socket factory.
+ * If this scheme is {@link #isLayered layered}, the factory implements
+ * {@link LayeredSocketFactory LayeredSocketFactory}.
+ *
+ * @return the socket factory for this scheme
+ *
+ * @deprecated (4.1) Use {@link #getSchemeSocketFactory()}
+ */
+ @Deprecated
+ public final SocketFactory getSocketFactory() {
+ if (this.socketFactory instanceof SchemeSocketFactoryAdaptor) {
+ return ((SchemeSocketFactoryAdaptor) this.socketFactory).getFactory();
+ } else {
+ if (this.layered) {
+ return new LayeredSocketFactoryAdaptor(
+ (LayeredSchemeSocketFactory) this.socketFactory);
+ } else {
+ return new SocketFactoryAdaptor(this.socketFactory);
+ }
+ }
+ }
+
+ /**
+ * Obtains the socket factory.
+ * If this scheme is {@link #isLayered layered}, the factory implements
+ * {@link LayeredSocketFactory LayeredSchemeSocketFactory}.
+ *
+ * @return the socket factory for this scheme
+ *
+ * @since 4.1
+ */
+ public final SchemeSocketFactory getSchemeSocketFactory() {
+ return this.socketFactory;
+ }
+
+ /**
+ * Obtains the scheme name.
+ *
+ * @return the name of this scheme, in lowercase
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Indicates whether this scheme allows for layered connections.
+ *
+ * @return <code>true</code> if layered connections are possible,
+ * <code>false</code> otherwise
+ */
+ public final boolean isLayered() {
+ return layered;
+ }
+
+ /**
+ * Resolves the correct port for this scheme.
+ * Returns the given port if it is valid, the default port otherwise.
+ *
+ * @param port the port to be resolved,
+ * a negative number to obtain the default port
+ *
+ * @return the given port or the defaultPort
+ */
+ public final int resolvePort(final int port) {
+ return port <= 0 ? defaultPort : port;
+ }
+
+ /**
+ * Return a string representation of this object.
+ *
+ * @return a human-readable string description of this scheme
+ */
+ @Override
+ public final String toString() {
+ if (stringRep == null) {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(this.name);
+ buffer.append(':');
+ buffer.append(Integer.toString(this.defaultPort));
+ stringRep = buffer.toString();
+ }
+ return stringRep;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Scheme) {
+ final Scheme that = (Scheme) obj;
+ return this.name.equals(that.name)
+ && this.defaultPort == that.defaultPort
+ && this.layered == that.layered;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.defaultPort);
+ hash = LangUtils.hashCode(hash, this.name);
+ hash = LangUtils.hashCode(hash, this.layered);
+ return hash;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactory.java
new file mode 100644
index 000000000..b20ada328
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactory.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * Extended {@link SchemeSocketFactory} interface for layered sockets such as SSL/TLS.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link
+ * ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory}
+ */
+@Deprecated
+public interface SchemeLayeredSocketFactory extends SchemeSocketFactory {
+
+ /**
+ * Returns a socket connected to the given host that is layered over an
+ * existing socket. Used primarily for creating secure sockets through
+ * proxies.
+ *
+ * @param socket the existing socket
+ * @param target the name of the target host.
+ * @param port the port to connect to on the target host
+ * @param params HTTP parameters
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ * @throws UnknownHostException if the IP address of the host cannot be
+ * determined
+ */
+ Socket createLayeredSocket(
+ Socket socket,
+ String target,
+ int port,
+ HttpParams params) throws IOException, UnknownHostException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor.java
new file mode 100644
index 000000000..098f55d9a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+class SchemeLayeredSocketFactoryAdaptor extends SchemeSocketFactoryAdaptor
+ implements SchemeLayeredSocketFactory {
+
+ private final LayeredSocketFactory factory;
+
+ SchemeLayeredSocketFactoryAdaptor(final LayeredSocketFactory factory) {
+ super(factory);
+ this.factory = factory;
+ }
+
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target, final int port,
+ final HttpParams params) throws IOException, UnknownHostException {
+ return this.factory.createSocket(socket, target, port, true);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor2.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor2.java
new file mode 100644
index 000000000..97f0442d7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor2.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+class SchemeLayeredSocketFactoryAdaptor2 implements SchemeLayeredSocketFactory {
+
+ private final LayeredSchemeSocketFactory factory;
+
+ SchemeLayeredSocketFactoryAdaptor2(final LayeredSchemeSocketFactory factory) {
+ super();
+ this.factory = factory;
+ }
+
+ public Socket createSocket(final HttpParams params) throws IOException {
+ return this.factory.createSocket(params);
+ }
+
+ public Socket connectSocket(
+ final Socket sock,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
+ return this.factory.connectSocket(sock, remoteAddress, localAddress, params);
+ }
+
+ public boolean isSecure(final Socket sock) throws IllegalArgumentException {
+ return this.factory.isSecure(sock);
+ }
+
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target, final int port,
+ final HttpParams params) throws IOException, UnknownHostException {
+ return this.factory.createLayeredSocket(socket, target, port, true);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeRegistry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeRegistry.java
new file mode 100644
index 000000000..ef87c809d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeRegistry.java
@@ -0,0 +1,168 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A set of supported protocol {@link Scheme}s.
+ * Schemes are identified by lowercase names.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.config.Registry}
+ */
+@ThreadSafe
+@Deprecated
+public final class SchemeRegistry {
+
+ /** The available schemes in this registry. */
+ private final ConcurrentHashMap<String,Scheme> registeredSchemes;
+
+ /**
+ * Creates a new, empty scheme registry.
+ */
+ public SchemeRegistry() {
+ super();
+ registeredSchemes = new ConcurrentHashMap<String,Scheme>();
+ }
+
+ /**
+ * Obtains a scheme by name.
+ *
+ * @param name the name of the scheme to look up (in lowercase)
+ *
+ * @return the scheme, never <code>null</code>
+ *
+ * @throws IllegalStateException
+ * if the scheme with the given name is not registered
+ */
+ public final Scheme getScheme(final String name) {
+ final Scheme found = get(name);
+ if (found == null) {
+ throw new IllegalStateException
+ ("Scheme '"+name+"' not registered.");
+ }
+ return found;
+ }
+
+ /**
+ * Obtains the scheme for a host.
+ * Convenience method for <code>getScheme(host.getSchemeName())</pre>
+ *
+ * @param host the host for which to obtain the scheme
+ *
+ * @return the scheme for the given host, never <code>null</code>
+ *
+ * @throws IllegalStateException
+ * if a scheme with the respective name is not registered
+ */
+ public final Scheme getScheme(final HttpHost host) {
+ Args.notNull(host, "Host");
+ return getScheme(host.getSchemeName());
+ }
+
+ /**
+ * Obtains a scheme by name, if registered.
+ *
+ * @param name the name of the scheme to look up (in lowercase)
+ *
+ * @return the scheme, or
+ * <code>null</code> if there is none by this name
+ */
+ public final Scheme get(final String name) {
+ Args.notNull(name, "Scheme name");
+ // leave it to the caller to use the correct name - all lowercase
+ //name = name.toLowerCase(Locale.ENGLISH);
+ final Scheme found = registeredSchemes.get(name);
+ return found;
+ }
+
+ /**
+ * Registers a scheme.
+ * The scheme can later be retrieved by its name
+ * using {@link #getScheme(String) getScheme} or {@link #get get}.
+ *
+ * @param sch the scheme to register
+ *
+ * @return the scheme previously registered with that name, or
+ * <code>null</code> if none was registered
+ */
+ public final Scheme register(final Scheme sch) {
+ Args.notNull(sch, "Scheme");
+ final Scheme old = registeredSchemes.put(sch.getName(), sch);
+ return old;
+ }
+
+ /**
+ * Unregisters a scheme.
+ *
+ * @param name the name of the scheme to unregister (in lowercase)
+ *
+ * @return the unregistered scheme, or
+ * <code>null</code> if there was none
+ */
+ public final Scheme unregister(final String name) {
+ Args.notNull(name, "Scheme name");
+ // leave it to the caller to use the correct name - all lowercase
+ //name = name.toLowerCase(Locale.ENGLISH);
+ final Scheme gone = registeredSchemes.remove(name);
+ return gone;
+ }
+
+ /**
+ * Obtains the names of the registered schemes.
+ *
+ * @return List containing registered scheme names.
+ */
+ public final List<String> getSchemeNames() {
+ return new ArrayList<String>(registeredSchemes.keySet());
+ }
+
+ /**
+ * Populates the internal collection of registered {@link Scheme protocol schemes}
+ * with the content of the map passed as a parameter.
+ *
+ * @param map protocol schemes
+ */
+ public void setItems(final Map<String, Scheme> map) {
+ if (map == null) {
+ return;
+ }
+ registeredSchemes.clear();
+ registeredSchemes.putAll(map);
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java
new file mode 100644
index 000000000..81cac0ed1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java
@@ -0,0 +1,130 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * A factory for creating, initializing and connecting sockets. The factory encapsulates the logic
+ * for establishing a socket connection.
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.conn.socket.ConnectionSocketFactory}
+ */
+@Deprecated
+public interface SchemeSocketFactory {
+
+ /**
+ * Creates a new, unconnected socket. The socket should subsequently be passed to
+ * {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}.
+ *
+ * @param params Optional {@link HttpParams parameters}. In most cases these parameters
+ * will not be required and will have no effect, as usually socket
+ * initialization should take place in the
+ * {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}
+ * method. However, in rare cases one may want to pass additional parameters
+ * to this method in order to create a customized {@link Socket} instance,
+ * for instance bound to a SOCKS proxy server.
+ *
+ * @return a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ */
+ Socket createSocket(HttpParams params) throws IOException;
+
+ /**
+ * Connects a socket to the target host with the given remote address.
+ * <p/>
+ * Please note that {@link ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress} class should
+ * be used in order to pass the target remote address along with the original
+ * {@link ch.boye.httpclientandroidlib.HttpHost} value used to resolve the address. The use of
+ * {@link ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress} can also ensure that no reverse
+ * DNS lookup will be performed if the target remote address was specified
+ * as an IP address.
+ *
+ * @param sock the socket to connect, as obtained from
+ * {@link #createSocket(HttpParams) createSocket}.
+ * <code>null</code> indicates that a new socket
+ * should be created and connected.
+ * @param remoteAddress the remote address to connect to.
+ * @param localAddress the local address to bind the socket to, or
+ * <code>null</code> for any
+ * @param params additional {@link HttpParams parameters} for connecting
+ *
+ * @return the connected socket. The returned object may be different
+ * from the <code>sock</code> argument if this factory supports
+ * a layered protocol.
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnknownHostException if the IP address of the target host
+ * can not be determined
+ * @throws ConnectTimeoutException if the socket cannot be connected
+ * within the time limit defined in the <code>params</code>
+ *
+ * @see ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress
+ */
+ Socket connectSocket(
+ Socket sock,
+ InetSocketAddress remoteAddress,
+ InetSocketAddress localAddress,
+ HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException;
+
+ /**
+ * Checks whether a socket provides a secure connection. The socket must be
+ * {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams) connected}
+ * by this factory. The factory will <i>not</i> perform I/O operations in this method.
+ * <p>
+ * As a rule of thumb, plain sockets are not secure and TLS/SSL sockets are secure. However,
+ * there may be application specific deviations. For example, a plain socket to a host in the
+ * same intranet ("trusted zone") could be considered secure. On the other hand, a TLS/SSL
+ * socket could be considered insecure based on the cipher suite chosen for the connection.
+ *
+ * @param sock the connected socket to check
+ *
+ * @return <code>true</code> if the connection of the socket
+ * should be considered secure, or
+ * <code>false</code> if it should not
+ *
+ * @throws IllegalArgumentException
+ * if the argument is invalid, for example because it is
+ * not a connected socket or was created by a different
+ * socket factory.
+ * Note that socket factories are <i>not</i> required to
+ * check these conditions, they may simply return a default
+ * value when called with an invalid socket argument.
+ */
+ boolean isSecure(Socket sock) throws IllegalArgumentException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java
new file mode 100644
index 000000000..85ff5e6b2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java
@@ -0,0 +1,100 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * @deprecated (4.1) do not use
+ */
+@Deprecated
+class SchemeSocketFactoryAdaptor implements SchemeSocketFactory {
+
+ private final SocketFactory factory;
+
+ SchemeSocketFactoryAdaptor(final SocketFactory factory) {
+ super();
+ this.factory = factory;
+ }
+
+ public Socket connectSocket(
+ final Socket sock,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
+ final String host = remoteAddress.getHostName();
+ final int port = remoteAddress.getPort();
+ InetAddress local = null;
+ int localPort = 0;
+ if (localAddress != null) {
+ local = localAddress.getAddress();
+ localPort = localAddress.getPort();
+ }
+ return this.factory.connectSocket(sock, host, port, local, localPort, params);
+ }
+
+ public Socket createSocket(final HttpParams params) throws IOException {
+ return this.factory.createSocket();
+ }
+
+ public boolean isSecure(final Socket sock) throws IllegalArgumentException {
+ return this.factory.isSecure(sock);
+ }
+
+ public SocketFactory getFactory() {
+ return this.factory;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SchemeSocketFactoryAdaptor) {
+ return this.factory.equals(((SchemeSocketFactoryAdaptor)obj).factory);
+ } else {
+ return this.factory.equals(obj);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return this.factory.hashCode();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactory.java
new file mode 100644
index 000000000..71960194b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactory.java
@@ -0,0 +1,127 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * A factory for creating, initializing and connecting sockets.
+ * The factory encapsulates the logic for establishing a socket connection.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use {@link SchemeSocketFactory}
+ */
+@Deprecated
+public interface SocketFactory {
+
+ /**
+ * Creates a new, unconnected socket.
+ * The socket should subsequently be passed to
+ * {@link #connectSocket connectSocket}.
+ *
+ * @return a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ */
+ Socket createSocket()
+ throws IOException;
+
+ /**
+ * Connects a socket to the given host.
+ *
+ * @param sock the socket to connect, as obtained from
+ * {@link #createSocket createSocket}.
+ * <code>null</code> indicates that a new socket
+ * should be created and connected.
+ * @param host the host to connect to
+ * @param port the port to connect to on the host
+ * @param localAddress the local address to bind the socket to, or
+ * <code>null</code> for any
+ * @param localPort the port on the local machine,
+ * 0 or a negative number for any
+ * @param params additional {@link HttpParams parameters} for connecting
+ *
+ * @return the connected socket. The returned object may be different
+ * from the <code>sock</code> argument if this factory supports
+ * a layered protocol.
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnknownHostException if the IP address of the target host
+ * can not be determined
+ * @throws ConnectTimeoutException if the socket cannot be connected
+ * within the time limit defined in the <code>params</code>
+ */
+ Socket connectSocket(
+ Socket sock,
+ String host,
+ int port,
+ InetAddress localAddress,
+ int localPort,
+ HttpParams params
+ ) throws IOException, UnknownHostException, ConnectTimeoutException;
+
+ /**
+ * Checks whether a socket provides a secure connection.
+ * The socket must be {@link #connectSocket connected}
+ * by this factory.
+ * The factory will <i>not</i> perform I/O operations
+ * in this method.
+ * <br/>
+ * As a rule of thumb, plain sockets are not secure and
+ * TLS/SSL sockets are secure. However, there may be
+ * application specific deviations. For example, a plain
+ * socket to a host in the same intranet ("trusted zone")
+ * could be considered secure. On the other hand, a
+ * TLS/SSL socket could be considered insecure based on
+ * the cipher suite chosen for the connection.
+ *
+ * @param sock the connected socket to check
+ *
+ * @return <code>true</code> if the connection of the socket
+ * should be considered secure, or
+ * <code>false</code> if it should not
+ *
+ * @throws IllegalArgumentException
+ * if the argument is invalid, for example because it is
+ * not a connected socket or was created by a different
+ * socket factory.
+ * Note that socket factories are <i>not</i> required to
+ * check these conditions, they may simply return a default
+ * value when called with an invalid socket argument.
+ */
+ boolean isSecure(Socket sock)
+ throws IllegalArgumentException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java
new file mode 100644
index 000000000..0e9aab355
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java
@@ -0,0 +1,97 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.params.BasicHttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+@Deprecated
+class SocketFactoryAdaptor implements SocketFactory {
+
+ private final SchemeSocketFactory factory;
+
+ SocketFactoryAdaptor(final SchemeSocketFactory factory) {
+ super();
+ this.factory = factory;
+ }
+
+ public Socket createSocket() throws IOException {
+ final HttpParams params = new BasicHttpParams();
+ return this.factory.createSocket(params);
+ }
+
+ public Socket connectSocket(
+ final Socket socket,
+ final String host, final int port,
+ final InetAddress localAddress, final int localPort,
+ final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
+ InetSocketAddress local = null;
+ if (localAddress != null || localPort > 0) {
+ local = new InetSocketAddress(localAddress, localPort > 0 ? localPort : 0);
+ }
+ final InetAddress remoteAddress = InetAddress.getByName(host);
+ final InetSocketAddress remote = new InetSocketAddress(remoteAddress, port);
+ return this.factory.connectSocket(socket, remote, local, params);
+ }
+
+ public boolean isSecure(final Socket socket) throws IllegalArgumentException {
+ return this.factory.isSecure(socket);
+ }
+
+ public SchemeSocketFactory getFactory() {
+ return this.factory;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SocketFactoryAdaptor) {
+ return this.factory.equals(((SocketFactoryAdaptor)obj).factory);
+ } else {
+ return this.factory.equals(obj);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return this.factory.hashCode();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/package-info.java
new file mode 100644
index 000000000..2e6409084
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Deprecated.
+ * @deprecated (4.3).
+ */
+package ch.boye.httpclientandroidlib.conn.scheme;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/ConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/ConnectionSocketFactory.java
new file mode 100644
index 000000000..98274f213
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/ConnectionSocketFactory.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.socket;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A factory for creating and connecting connection sockets.
+ *
+ * @since 4.3
+ */
+public interface ConnectionSocketFactory {
+
+ /**
+ * Creates new, unconnected socket. The socket should subsequently be passed to
+ * {@link #connectSocket(int, Socket, HttpHost, InetSocketAddress, InetSocketAddress,
+ * HttpContext) connectSocket} method.
+ *
+ * @return a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ */
+ Socket createSocket(HttpContext context) throws IOException;
+
+ /**
+ * Connects the socket to the target host with the given resolved remote address.
+ *
+ * @param connectTimeout connect timeout.
+ * @param sock the socket to connect, as obtained from {@link #createSocket(HttpContext)}.
+ * <code>null</code> indicates that a new socket should be created and connected.
+ * @param host target host as specified by the caller (end user).
+ * @param remoteAddress the resolved remote address to connect to.
+ * @param localAddress the local address to bind the socket to, or <code>null</code> for any.
+ * @param context the actual HTTP context.
+ *
+ * @return the connected socket. The returned object may be different
+ * from the <code>sock</code> argument if this factory supports
+ * a layered protocol.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ Socket connectSocket(
+ int connectTimeout,
+ Socket sock,
+ HttpHost host,
+ InetSocketAddress remoteAddress,
+ InetSocketAddress localAddress,
+ HttpContext context) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/LayeredConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/LayeredConnectionSocketFactory.java
new file mode 100644
index 000000000..40c54f8fa
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/LayeredConnectionSocketFactory.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.socket;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Extended {@link ConnectionSocketFactory} interface for layered sockets such as SSL/TLS.
+ *
+ * @since 4.3
+ */
+public interface LayeredConnectionSocketFactory extends ConnectionSocketFactory {
+
+ /**
+ * Returns a socket connected to the given host that is layered over an
+ * existing socket. Used primarily for creating secure sockets through
+ * proxies.
+ *
+ * @param socket the existing socket
+ * @param target the name of the target host.
+ * @param port the port to connect to on the target host.
+ * @param context the actual HTTP context.
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ */
+ Socket createLayeredSocket(
+ Socket socket,
+ String target,
+ int port,
+ HttpContext context) throws IOException, UnknownHostException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/PlainConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/PlainConnectionSocketFactory.java
new file mode 100644
index 000000000..d8fa807c5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/PlainConnectionSocketFactory.java
@@ -0,0 +1,83 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.socket;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * The default class for creating plain (unencrypted) sockets.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class PlainConnectionSocketFactory implements ConnectionSocketFactory {
+
+ public static final PlainConnectionSocketFactory INSTANCE = new PlainConnectionSocketFactory();
+
+ public static PlainConnectionSocketFactory getSocketFactory() {
+ return INSTANCE;
+ }
+
+ public PlainConnectionSocketFactory() {
+ super();
+ }
+
+ public Socket createSocket(final HttpContext context) throws IOException {
+ return new Socket();
+ }
+
+ public Socket connectSocket(
+ final int connectTimeout,
+ final Socket socket,
+ final HttpHost host,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final HttpContext context) throws IOException {
+ final Socket sock = socket != null ? socket : createSocket(context);
+ if (localAddress != null) {
+ sock.bind(localAddress);
+ }
+ try {
+ sock.connect(remoteAddress, connectTimeout);
+ } catch (final IOException ex) {
+ try {
+ sock.close();
+ } catch (final IOException ignore) {
+ }
+ throw ex;
+ }
+ return sock;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/package-info.java
new file mode 100644
index 000000000..fb73d60de
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client connection socket APIs.
+ */
+package ch.boye.httpclientandroidlib.conn.socket;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AbstractVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AbstractVerifier.java
new file mode 100644
index 000000000..24a7b40a8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AbstractVerifier.java
@@ -0,0 +1,386 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.util.InetAddressUtils;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+import ch.boye.httpclientandroidlib.NameValuePair;
+
+
+/**
+ * Abstract base class for all standard {@link X509HostnameVerifier}
+ * implementations.
+ *
+ * @since 4.0
+ */
+@Immutable
+public abstract class AbstractVerifier implements X509HostnameVerifier {
+
+ /**
+ * This contains a list of 2nd-level domains that aren't allowed to
+ * have wildcards when combined with country-codes.
+ * For example: [*.co.uk].
+ * <p/>
+ * The [*.co.uk] problem is an interesting one. Should we just hope
+ * that CA's would never foolishly allow such a certificate to happen?
+ * Looks like we're the only implementation guarding against this.
+ * Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check.
+ */
+ private final static String[] BAD_COUNTRY_2LDS =
+ { "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
+ "lg", "ne", "net", "or", "org" };
+
+ static {
+ // Just in case developer forgot to manually sort the array. :-)
+ Arrays.sort(BAD_COUNTRY_2LDS);
+ }
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public AbstractVerifier() {
+ super();
+ }
+
+ public final void verify(final String host, final SSLSocket ssl)
+ throws IOException {
+ if(host == null) {
+ throw new NullPointerException("host to verify is null");
+ }
+
+ SSLSession session = ssl.getSession();
+ if(session == null) {
+ // In our experience this only happens under IBM 1.4.x when
+ // spurious (unrelated) certificates show up in the server'
+ // chain. Hopefully this will unearth the real problem:
+ final InputStream in = ssl.getInputStream();
+ in.available();
+ /*
+ If you're looking at the 2 lines of code above because
+ you're running into a problem, you probably have two
+ options:
+
+ #1. Clean up the certificate chain that your server
+ is presenting (e.g. edit "/etc/apache2/server.crt"
+ or wherever it is your server's certificate chain
+ is defined).
+
+ OR
+
+ #2. Upgrade to an IBM 1.5.x or greater JVM, or switch
+ to a non-IBM JVM.
+ */
+
+ // If ssl.getInputStream().available() didn't cause an
+ // exception, maybe at least now the session is available?
+ session = ssl.getSession();
+ if(session == null) {
+ // If it's still null, probably a startHandshake() will
+ // unearth the real problem.
+ ssl.startHandshake();
+
+ // Okay, if we still haven't managed to cause an exception,
+ // might as well go for the NPE. Or maybe we're okay now?
+ session = ssl.getSession();
+ }
+ }
+
+ final Certificate[] certs = session.getPeerCertificates();
+ final X509Certificate x509 = (X509Certificate) certs[0];
+ verify(host, x509);
+ }
+
+ public final boolean verify(final String host, final SSLSession session) {
+ try {
+ final Certificate[] certs = session.getPeerCertificates();
+ final X509Certificate x509 = (X509Certificate) certs[0];
+ verify(host, x509);
+ return true;
+ }
+ catch(final SSLException e) {
+ return false;
+ }
+ }
+
+ public final void verify(final String host, final X509Certificate cert)
+ throws SSLException {
+ final String[] cns = getCNs(cert);
+ final String[] subjectAlts = getSubjectAlts(cert, host);
+ verify(host, cns, subjectAlts);
+ }
+
+ public final void verify(final String host, final String[] cns,
+ final String[] subjectAlts,
+ final boolean strictWithSubDomains)
+ throws SSLException {
+
+ // Build the list of names we're going to check. Our DEFAULT and
+ // STRICT implementations of the HostnameVerifier only use the
+ // first CN provided. All other CNs are ignored.
+ // (Firefox, wget, curl, Sun Java 1.4, 5, 6 all work this way).
+ final LinkedList<String> names = new LinkedList<String>();
+ if(cns != null && cns.length > 0 && cns[0] != null) {
+ names.add(cns[0]);
+ }
+ if(subjectAlts != null) {
+ for (final String subjectAlt : subjectAlts) {
+ if (subjectAlt != null) {
+ names.add(subjectAlt);
+ }
+ }
+ }
+
+ if(names.isEmpty()) {
+ final String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
+ throw new SSLException(msg);
+ }
+
+ // StringBuilder for building the error message.
+ final StringBuilder buf = new StringBuilder();
+
+ // We're can be case-insensitive when comparing the host we used to
+ // establish the socket to the hostname in the certificate.
+ final String hostName = normaliseIPv6Address(host.trim().toLowerCase(Locale.ENGLISH));
+ boolean match = false;
+ for(final Iterator<String> it = names.iterator(); it.hasNext();) {
+ // Don't trim the CN, though!
+ String cn = it.next();
+ cn = cn.toLowerCase(Locale.ENGLISH);
+ // Store CN in StringBuilder in case we need to report an error.
+ buf.append(" <");
+ buf.append(cn);
+ buf.append('>');
+ if(it.hasNext()) {
+ buf.append(" OR");
+ }
+
+ // The CN better have at least two dots if it wants wildcard
+ // action. It also can't be [*.co.uk] or [*.co.jp] or
+ // [*.org.uk], etc...
+ final String parts[] = cn.split("\\.");
+ final boolean doWildcard =
+ parts.length >= 3 && parts[0].endsWith("*") &&
+ validCountryWildcard(cn) && !isIPAddress(host);
+
+ if(doWildcard) {
+ final String firstpart = parts[0];
+ if (firstpart.length() > 1) { // e.g. server*
+ final String prefix = firstpart.substring(0, firstpart.length() - 1); // e.g. server
+ final String suffix = cn.substring(firstpart.length()); // skip wildcard part from cn
+ final String hostSuffix = hostName.substring(prefix.length()); // skip wildcard part from host
+ match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
+ } else {
+ match = hostName.endsWith(cn.substring(1));
+ }
+ if(match && strictWithSubDomains) {
+ // If we're in strict mode, then [*.foo.com] is not
+ // allowed to match [a.b.foo.com]
+ match = countDots(hostName) == countDots(cn);
+ }
+ } else {
+ match = hostName.equals(normaliseIPv6Address(cn));
+ }
+ if(match) {
+ break;
+ }
+ }
+ if(!match) {
+ throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
+ }
+ }
+
+ /**
+ * @deprecated (4.3.1) should not be a part of public APIs.
+ */
+ @Deprecated
+ public static boolean acceptableCountryWildcard(final String cn) {
+ final String parts[] = cn.split("\\.");
+ if (parts.length != 3 || parts[2].length() != 2) {
+ return true; // it's not an attempt to wildcard a 2TLD within a country code
+ }
+ return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
+ }
+
+ boolean validCountryWildcard(final String cn) {
+ final String parts[] = cn.split("\\.");
+ if (parts.length != 3 || parts[2].length() != 2) {
+ return true; // it's not an attempt to wildcard a 2TLD within a country code
+ }
+ return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
+ }
+
+ public static String[] getCNs(final X509Certificate cert) {
+ final String subjectPrincipal = cert.getSubjectX500Principal().toString();
+ try {
+ return extractCNs(subjectPrincipal);
+ } catch (SSLException ex) {
+ return null;
+ }
+ }
+
+ static String[] extractCNs(final String subjectPrincipal) throws SSLException {
+ if (subjectPrincipal == null) {
+ return null;
+ }
+ final List<String> cns = new ArrayList<String>();
+ final List<NameValuePair> nvps = DistinguishedNameParser.INSTANCE.parse(subjectPrincipal);
+ for (int i = 0; i < nvps.size(); i++) {
+ final NameValuePair nvp = nvps.get(i);
+ final String attribName = nvp.getName();
+ final String attribValue = nvp.getValue();
+ if (TextUtils.isBlank(attribValue)) {
+ throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name");
+ }
+ if (attribName.equalsIgnoreCase("cn")) {
+ cns.add(attribValue);
+ }
+ }
+ return cns.isEmpty() ? null : cns.toArray(new String[ cns.size() ]);
+ }
+
+ /**
+ * Extracts the array of SubjectAlt DNS or IP names from an X509Certificate.
+ * Returns null if there aren't any.
+ *
+ * @param cert X509Certificate
+ * @param hostname
+ * @return Array of SubjectALT DNS or IP names stored in the certificate.
+ */
+ private static String[] getSubjectAlts(
+ final X509Certificate cert, final String hostname) {
+ final int subjectType;
+ if (isIPAddress(hostname)) {
+ subjectType = 7;
+ } else {
+ subjectType = 2;
+ }
+
+ final LinkedList<String> subjectAltList = new LinkedList<String>();
+ Collection<List<?>> c = null;
+ try {
+ c = cert.getSubjectAlternativeNames();
+ }
+ catch(final CertificateParsingException cpe) {
+ }
+ if(c != null) {
+ for (final List<?> aC : c) {
+ final List<?> list = aC;
+ final int type = ((Integer) list.get(0)).intValue();
+ if (type == subjectType) {
+ final String s = (String) list.get(1);
+ subjectAltList.add(s);
+ }
+ }
+ }
+ if(!subjectAltList.isEmpty()) {
+ final String[] subjectAlts = new String[subjectAltList.size()];
+ subjectAltList.toArray(subjectAlts);
+ return subjectAlts;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Extracts the array of SubjectAlt DNS names from an X509Certificate.
+ * Returns null if there aren't any.
+ * <p/>
+ * Note: Java doesn't appear able to extract international characters
+ * from the SubjectAlts. It can only extract international characters
+ * from the CN field.
+ * <p/>
+ * (Or maybe the version of OpenSSL I'm using to test isn't storing the
+ * international characters correctly in the SubjectAlts?).
+ *
+ * @param cert X509Certificate
+ * @return Array of SubjectALT DNS names stored in the certificate.
+ */
+ public static String[] getDNSSubjectAlts(final X509Certificate cert) {
+ return getSubjectAlts(cert, null);
+ }
+
+ /**
+ * Counts the number of dots "." in a string.
+ * @param s string to count dots from
+ * @return number of dots
+ */
+ public static int countDots(final String s) {
+ int count = 0;
+ for(int i = 0; i < s.length(); i++) {
+ if(s.charAt(i) == '.') {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private static boolean isIPAddress(final String hostname) {
+ return hostname != null &&
+ (InetAddressUtils.isIPv4Address(hostname) ||
+ InetAddressUtils.isIPv6Address(hostname));
+ }
+
+ /*
+ * Check if hostname is IPv6, and if so, convert to standard format.
+ */
+ private String normaliseIPv6Address(final String hostname) {
+ if (hostname == null || !InetAddressUtils.isIPv6Address(hostname)) {
+ return hostname;
+ }
+ try {
+ final InetAddress inetAddress = InetAddress.getByName(hostname);
+ return inetAddress.getHostAddress();
+ } catch (final UnknownHostException uhe) { // Should not happen, because we check for IPv6 address above
+ log.error("Unexpected error converting "+hostname, uhe);
+ return hostname;
+ }
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java
new file mode 100644
index 000000000..8ca1fad5a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * The ALLOW_ALL HostnameVerifier essentially turns hostname verification
+ * off. This implementation is a no-op, and never throws the SSLException.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class AllowAllHostnameVerifier extends AbstractVerifier {
+
+ public final void verify(
+ final String host,
+ final String[] cns,
+ final String[] subjectAlts) {
+ // Allow everything - so never blowup.
+ }
+
+ @Override
+ public final String toString() {
+ return "ALLOW_ALL";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java
new file mode 100644
index 000000000..05f7d8c8c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import javax.net.ssl.SSLException;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * The HostnameVerifier that works the same way as Curl and Firefox.
+ * <p/>
+ * The hostname must match either the first CN, or any of the subject-alts.
+ * A wildcard can occur in the CN, and in any of the subject-alts.
+ * <p/>
+ * The only difference between BROWSER_COMPATIBLE and STRICT is that a wildcard
+ * (such as "*.foo.com") with BROWSER_COMPATIBLE matches all subdomains,
+ * including "a.b.foo.com".
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BrowserCompatHostnameVerifier extends AbstractVerifier {
+
+ public final void verify(
+ final String host,
+ final String[] cns,
+ final String[] subjectAlts) throws SSLException {
+ verify(host, cns, subjectAlts, false);
+ }
+
+ @Override
+ boolean validCountryWildcard(final String cn) {
+ return true;
+ }
+
+ @Override
+ public final String toString() {
+ return "BROWSER_COMPATIBLE";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/DistinguishedNameParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/DistinguishedNameParser.java
new file mode 100644
index 000000000..98b2ec3a9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/DistinguishedNameParser.java
@@ -0,0 +1,131 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+@Immutable
+final class DistinguishedNameParser {
+
+ public final static DistinguishedNameParser INSTANCE = new DistinguishedNameParser();
+
+ private static final BitSet EQUAL_OR_COMMA_OR_PLUS = TokenParser.INIT_BITSET('=', ',', '+');
+ private static final BitSet COMMA_OR_PLUS = TokenParser.INIT_BITSET(',', '+');
+
+ private final TokenParser tokenParser;
+
+ DistinguishedNameParser() {
+ this.tokenParser = new InternalTokenParser();
+ }
+
+ String parseToken(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) {
+ return tokenParser.parseToken(buf, cursor, delimiters);
+ }
+
+ String parseValue(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) {
+ return tokenParser.parseValue(buf, cursor, delimiters);
+ }
+
+ NameValuePair parseParameter(final CharArrayBuffer buf, final ParserCursor cursor) {
+ final String name = parseToken(buf, cursor, EQUAL_OR_COMMA_OR_PLUS);
+ if (cursor.atEnd()) {
+ return new BasicNameValuePair(name, null);
+ }
+ final int delim = buf.charAt(cursor.getPos());
+ cursor.updatePos(cursor.getPos() + 1);
+ if (delim == ',') {
+ return new BasicNameValuePair(name, null);
+ }
+ final String value = parseValue(buf, cursor, COMMA_OR_PLUS);
+ if (!cursor.atEnd()) {
+ cursor.updatePos(cursor.getPos() + 1);
+ }
+ return new BasicNameValuePair(name, value);
+ }
+
+ public List<NameValuePair> parse(final CharArrayBuffer buf, final ParserCursor cursor) {
+ final List<NameValuePair> params = new ArrayList<NameValuePair>();
+ tokenParser.skipWhiteSpace(buf, cursor);
+ while (!cursor.atEnd()) {
+ final NameValuePair param = parseParameter(buf, cursor);
+ params.add(param);
+ }
+ return params;
+ }
+
+ public List<NameValuePair> parse(final String s) {
+ if (s == null) {
+ return null;
+ }
+ final CharArrayBuffer buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ final ParserCursor cursor = new ParserCursor(0, s.length());
+ return parse(buffer, cursor);
+ }
+
+ static class InternalTokenParser extends TokenParser {
+
+ @Override
+ public void copyUnquotedContent(
+ final CharArrayBuffer buf,
+ final ParserCursor cursor,
+ final BitSet delimiters,
+ final StringBuilder dst) {
+ int pos = cursor.getPos();
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+ boolean escaped = false;
+ for (int i = indexFrom; i < indexTo; i++, pos++) {
+ final char current = buf.charAt(i);
+ if (escaped) {
+ dst.append(current);
+ escaped = false;
+ } else {
+ if ((delimiters != null && delimiters.get(current))
+ || TokenParser.isWhitespace(current) || current == '\"') {
+ break;
+ } else if (current == '\\') {
+ escaped = true;
+ } else {
+ dst.append(current);
+ }
+ }
+ }
+ cursor.updatePos(pos);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyDetails.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyDetails.java
new file mode 100644
index 000000000..c85978550
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyDetails.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+
+/**
+ * Private key details.
+ *
+ * @since 4.3
+ */
+public final class PrivateKeyDetails {
+
+ private final String type;
+ private final X509Certificate[] certChain;
+
+ public PrivateKeyDetails(final String type, final X509Certificate[] certChain) {
+ super();
+ this.type = Args.notNull(type, "Private key type");
+ this.certChain = certChain;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public X509Certificate[] getCertChain() {
+ return certChain;
+ }
+
+ @Override
+ public String toString() {
+ return type + ':' + Arrays.toString(certChain);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyStrategy.java
new file mode 100644
index 000000000..ba3ba40c5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyStrategy.java
@@ -0,0 +1,44 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.net.Socket;
+import java.util.Map;
+
+/**
+ * A strategy allowing for a choice of an alias during SSL authentication.
+ *
+ * @since 4.3
+ */
+public interface PrivateKeyStrategy {
+
+ /**
+ * Determines what key material to use for SSL authentication.
+ */
+ String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLConnectionSocketFactory.java
new file mode 100644
index 000000000..341fbe385
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLConnectionSocketFactory.java
@@ -0,0 +1,295 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+/**
+ * Layered socket factory for TLS/SSL connections.
+ * <p>
+ * SSLSocketFactory can be used to validate the identity of the HTTPS server against a list of
+ * trusted certificates and to authenticate to the HTTPS server using a private key.
+ * <p>
+ * SSLSocketFactory will enable server authentication when supplied with
+ * a {@link java.security.KeyStore trust-store} file containing one or several trusted certificates. The client
+ * secure socket will reject the connection during the SSL session handshake if the target HTTPS
+ * server attempts to authenticate itself with a non-trusted certificate.
+ * <p>
+ * Use JDK keytool utility to import a trusted certificate and generate a trust-store file:
+ * <pre>
+ * keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
+ * </pre>
+ * <p>
+ * In special cases the standard trust verification process can be bypassed by using a custom
+ * {@link ch.boye.httpclientandroidlib.conn.ssl.TrustStrategy}. This interface is primarily intended for allowing self-signed
+ * certificates to be accepted as trusted without having to add them to the trust-store file.
+ * <p>
+ * SSLSocketFactory will enable client authentication when supplied with
+ * a {@link java.security.KeyStore key-store} file containing a private key/public certificate
+ * pair. The client secure socket will use the private key to authenticate
+ * itself to the target HTTPS server during the SSL session handshake if
+ * requested to do so by the server.
+ * The target HTTPS server will in its turn verify the certificate presented
+ * by the client in order to establish client's authenticity.
+ * <p>
+ * Use the following sequence of actions to generate a key-store file
+ * </p>
+ * <ul>
+ * <li>
+ * <p>
+ * Use JDK keytool utility to generate a new key
+ * <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
+ * For simplicity use the same password for the key as that of the key-store
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Issue a certificate signing request (CSR)
+ * <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Send the certificate request to the trusted Certificate Authority for signature.
+ * One may choose to act as her own CA and sign the certificate request using a PKI
+ * tool, such as OpenSSL.
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Import the trusted CA root certificate
+ * <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Import the PKCS#7 file containg the complete certificate chain
+ * <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Verify the content the resultant keystore file
+ * <pre>keytool -list -v -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * </ul>
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class SSLConnectionSocketFactory implements LayeredConnectionSocketFactory {
+
+ public static final String TLS = "TLS";
+ public static final String SSL = "SSL";
+ public static final String SSLV2 = "SSLv2";
+
+ public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER
+ = new AllowAllHostnameVerifier();
+
+ public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
+ = new BrowserCompatHostnameVerifier();
+
+ public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER
+ = new StrictHostnameVerifier();
+
+ /**
+ * Obtains default SSL socket factory with an SSL context based on the standard JSSE
+ * trust material (<code>cacerts</code> file in the security properties directory).
+ * System properties are not taken into consideration.
+ *
+ * @return default SSL socket factory
+ */
+ public static SSLConnectionSocketFactory getSocketFactory() throws SSLInitializationException {
+ return new SSLConnectionSocketFactory(
+ SSLContexts.createDefault(),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ private static String[] split(final String s) {
+ if (TextUtils.isBlank(s)) {
+ return null;
+ }
+ return s.split(" *, *");
+ }
+
+ /**
+ * Obtains default SSL socket factory with an SSL context based on system properties
+ * as described in
+ * <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html">
+ * "JavaTM Secure Socket Extension (JSSE) Reference Guide for the JavaTM 2 Platform
+ * Standard Edition 5</a>
+ *
+ * @return default system SSL socket factory
+ */
+ public static SSLConnectionSocketFactory getSystemSocketFactory() throws SSLInitializationException {
+ return new SSLConnectionSocketFactory(
+ (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault(),
+ split(System.getProperty("https.protocols")),
+ split(System.getProperty("https.cipherSuites")),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ private final javax.net.ssl.SSLSocketFactory socketfactory;
+ private final X509HostnameVerifier hostnameVerifier;
+ private final String[] supportedProtocols;
+ private final String[] supportedCipherSuites;
+
+ public SSLConnectionSocketFactory(final SSLContext sslContext) {
+ this(sslContext, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ public SSLConnectionSocketFactory(
+ final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) {
+ this(Args.notNull(sslContext, "SSL context").getSocketFactory(),
+ null, null, hostnameVerifier);
+ }
+
+ public SSLConnectionSocketFactory(
+ final SSLContext sslContext,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final X509HostnameVerifier hostnameVerifier) {
+ this(Args.notNull(sslContext, "SSL context").getSocketFactory(),
+ supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ }
+
+ public SSLConnectionSocketFactory(
+ final javax.net.ssl.SSLSocketFactory socketfactory,
+ final X509HostnameVerifier hostnameVerifier) {
+ this(socketfactory, null, null, hostnameVerifier);
+ }
+
+ public SSLConnectionSocketFactory(
+ final javax.net.ssl.SSLSocketFactory socketfactory,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final X509HostnameVerifier hostnameVerifier) {
+ this.socketfactory = Args.notNull(socketfactory, "SSL socket factory");
+ this.supportedProtocols = supportedProtocols;
+ this.supportedCipherSuites = supportedCipherSuites;
+ this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+ }
+
+ /**
+ * Performs any custom initialization for a newly created SSLSocket
+ * (before the SSL handshake happens).
+ *
+ * The default implementation is a no-op, but could be overridden to, e.g.,
+ * call {@link javax.net.ssl.SSLSocket#setEnabledCipherSuites(String[])}.
+ */
+ protected void prepareSocket(final SSLSocket socket) throws IOException {
+ }
+
+ public Socket createSocket(final HttpContext context) throws IOException {
+ return SocketFactory.getDefault().createSocket();
+ }
+
+ public Socket connectSocket(
+ final int connectTimeout,
+ final Socket socket,
+ final HttpHost host,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final HttpContext context) throws IOException {
+ Args.notNull(host, "HTTP host");
+ Args.notNull(remoteAddress, "Remote address");
+ final Socket sock = socket != null ? socket : createSocket(context);
+ if (localAddress != null) {
+ sock.bind(localAddress);
+ }
+ try {
+ sock.connect(remoteAddress, connectTimeout);
+ } catch (final IOException ex) {
+ try {
+ sock.close();
+ } catch (final IOException ignore) {
+ }
+ throw ex;
+ }
+ // Setup SSL layering if necessary
+ if (sock instanceof SSLSocket) {
+ final SSLSocket sslsock = (SSLSocket) sock;
+ sslsock.startHandshake();
+ verifyHostname(sslsock, host.getHostName());
+ return sock;
+ } else {
+ return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context);
+ }
+ }
+
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target,
+ final int port,
+ final HttpContext context) throws IOException {
+ final SSLSocket sslsock = (SSLSocket) this.socketfactory.createSocket(
+ socket,
+ target,
+ port,
+ true);
+ if (supportedProtocols != null) {
+ sslsock.setEnabledProtocols(supportedProtocols);
+ }
+ if (supportedCipherSuites != null) {
+ sslsock.setEnabledCipherSuites(supportedCipherSuites);
+ }
+ prepareSocket(sslsock);
+ sslsock.startHandshake();
+ verifyHostname(sslsock, target);
+ return sslsock;
+ }
+
+ X509HostnameVerifier getHostnameVerifier() {
+ return this.hostnameVerifier;
+ }
+
+ private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException {
+ try {
+ this.hostnameVerifier.verify(hostname, sslsock);
+ // verifyHostName() didn't blowup - good!
+ } catch (final IOException iox) {
+ // close the socket before re-throwing the exception
+ try { sslsock.close(); } catch (final Exception x) { /*ignore*/ }
+ throw iox;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContextBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContextBuilder.java
new file mode 100644
index 000000000..89751a166
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContextBuilder.java
@@ -0,0 +1,259 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * Builder for {@link SSLContext} instances.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class SSLContextBuilder {
+
+ static final String TLS = "TLS";
+ static final String SSL = "SSL";
+
+ private String protocol;
+ private Set<KeyManager> keymanagers;
+ private Set<TrustManager> trustmanagers;
+ private SecureRandom secureRandom;
+
+ public SSLContextBuilder() {
+ super();
+ this.keymanagers = new HashSet<KeyManager>();
+ this.trustmanagers = new HashSet<TrustManager>();
+ }
+
+ public SSLContextBuilder useTLS() {
+ this.protocol = TLS;
+ return this;
+ }
+
+ public SSLContextBuilder useSSL() {
+ this.protocol = SSL;
+ return this;
+ }
+
+ public SSLContextBuilder useProtocol(final String protocol) {
+ this.protocol = protocol;
+ return this;
+ }
+
+ public SSLContextBuilder setSecureRandom(final SecureRandom secureRandom) {
+ this.secureRandom = secureRandom;
+ return this;
+ }
+
+ public SSLContextBuilder loadTrustMaterial(
+ final KeyStore truststore,
+ final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException {
+ final TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(
+ TrustManagerFactory.getDefaultAlgorithm());
+ tmfactory.init(truststore);
+ final TrustManager[] tms = tmfactory.getTrustManagers();
+ if (tms != null) {
+ if (trustStrategy != null) {
+ for (int i = 0; i < tms.length; i++) {
+ final TrustManager tm = tms[i];
+ if (tm instanceof X509TrustManager) {
+ tms[i] = new TrustManagerDelegate(
+ (X509TrustManager) tm, trustStrategy);
+ }
+ }
+ }
+ for (final TrustManager tm : tms) {
+ this.trustmanagers.add(tm);
+ }
+ }
+ return this;
+ }
+
+ public SSLContextBuilder loadTrustMaterial(
+ final KeyStore truststore) throws NoSuchAlgorithmException, KeyStoreException {
+ return loadTrustMaterial(truststore, null);
+ }
+
+ public SSLContextBuilder loadKeyMaterial(
+ final KeyStore keystore,
+ final char[] keyPassword)
+ throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
+ loadKeyMaterial(keystore, keyPassword, null);
+ return this;
+ }
+
+ public SSLContextBuilder loadKeyMaterial(
+ final KeyStore keystore,
+ final char[] keyPassword,
+ final PrivateKeyStrategy aliasStrategy)
+ throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
+ final KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
+ KeyManagerFactory.getDefaultAlgorithm());
+ kmfactory.init(keystore, keyPassword);
+ final KeyManager[] kms = kmfactory.getKeyManagers();
+ if (kms != null) {
+ if (aliasStrategy != null) {
+ for (int i = 0; i < kms.length; i++) {
+ final KeyManager km = kms[i];
+ if (km instanceof X509KeyManager) {
+ kms[i] = new KeyManagerDelegate(
+ (X509KeyManager) km, aliasStrategy);
+ }
+ }
+ }
+ for (final KeyManager km : kms) {
+ keymanagers.add(km);
+ }
+ }
+ return this;
+ }
+
+ public SSLContext build() throws NoSuchAlgorithmException, KeyManagementException {
+ final SSLContext sslcontext = SSLContext.getInstance(
+ this.protocol != null ? this.protocol : TLS);
+ sslcontext.init(
+ !keymanagers.isEmpty() ? keymanagers.toArray(new KeyManager[keymanagers.size()]) : null,
+ !trustmanagers.isEmpty() ? trustmanagers.toArray(new TrustManager[trustmanagers.size()]) : null,
+ secureRandom);
+ return sslcontext;
+ }
+
+ static class TrustManagerDelegate implements X509TrustManager {
+
+ private final X509TrustManager trustManager;
+ private final TrustStrategy trustStrategy;
+
+ TrustManagerDelegate(final X509TrustManager trustManager, final TrustStrategy trustStrategy) {
+ super();
+ this.trustManager = trustManager;
+ this.trustStrategy = trustStrategy;
+ }
+
+ public void checkClientTrusted(
+ final X509Certificate[] chain, final String authType) throws CertificateException {
+ this.trustManager.checkClientTrusted(chain, authType);
+ }
+
+ public void checkServerTrusted(
+ final X509Certificate[] chain, final String authType) throws CertificateException {
+ if (!this.trustStrategy.isTrusted(chain, authType)) {
+ this.trustManager.checkServerTrusted(chain, authType);
+ }
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return this.trustManager.getAcceptedIssuers();
+ }
+
+ }
+
+ static class KeyManagerDelegate implements X509KeyManager {
+
+ private final X509KeyManager keyManager;
+ private final PrivateKeyStrategy aliasStrategy;
+
+ KeyManagerDelegate(final X509KeyManager keyManager, final PrivateKeyStrategy aliasStrategy) {
+ super();
+ this.keyManager = keyManager;
+ this.aliasStrategy = aliasStrategy;
+ }
+
+ public String[] getClientAliases(
+ final String keyType, final Principal[] issuers) {
+ return this.keyManager.getClientAliases(keyType, issuers);
+ }
+
+ public String chooseClientAlias(
+ final String[] keyTypes, final Principal[] issuers, final Socket socket) {
+ final Map<String, PrivateKeyDetails> validAliases = new HashMap<String, PrivateKeyDetails>();
+ for (final String keyType: keyTypes) {
+ final String[] aliases = this.keyManager.getClientAliases(keyType, issuers);
+ if (aliases != null) {
+ for (final String alias: aliases) {
+ validAliases.put(alias,
+ new PrivateKeyDetails(keyType, this.keyManager.getCertificateChain(alias)));
+ }
+ }
+ }
+ return this.aliasStrategy.chooseAlias(validAliases, socket);
+ }
+
+ public String[] getServerAliases(
+ final String keyType, final Principal[] issuers) {
+ return this.keyManager.getServerAliases(keyType, issuers);
+ }
+
+ public String chooseServerAlias(
+ final String keyType, final Principal[] issuers, final Socket socket) {
+ final Map<String, PrivateKeyDetails> validAliases = new HashMap<String, PrivateKeyDetails>();
+ final String[] aliases = this.keyManager.getServerAliases(keyType, issuers);
+ if (aliases != null) {
+ for (final String alias: aliases) {
+ validAliases.put(alias,
+ new PrivateKeyDetails(keyType, this.keyManager.getCertificateChain(alias)));
+ }
+ }
+ return this.aliasStrategy.chooseAlias(validAliases, socket);
+ }
+
+ public X509Certificate[] getCertificateChain(final String alias) {
+ return this.keyManager.getCertificateChain(alias);
+ }
+
+ public PrivateKey getPrivateKey(final String alias) {
+ return this.keyManager.getPrivateKey(alias);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContexts.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContexts.java
new file mode 100644
index 000000000..a87a50168
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContexts.java
@@ -0,0 +1,90 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.SSLContext;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * {@link SSLContext} factory methods.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class SSLContexts {
+
+ /**
+ * Creates default factory based on the standard JSSE trust material
+ * (<code>cacerts</code> file in the security properties directory). System properties
+ * are not taken into consideration.
+ *
+ * @return the default SSL socket factory
+ */
+ public static SSLContext createDefault() throws SSLInitializationException {
+ try {
+ final SSLContext sslcontext = SSLContext.getInstance(SSLContextBuilder.TLS);
+ sslcontext.init(null, null, null);
+ return sslcontext;
+ } catch (final NoSuchAlgorithmException ex) {
+ throw new SSLInitializationException(ex.getMessage(), ex);
+ } catch (final KeyManagementException ex) {
+ throw new SSLInitializationException(ex.getMessage(), ex);
+ }
+ }
+
+ /**
+ * Creates default SSL context based on system properties. This method obtains
+ * default SSL context by calling <code>SSLContext.getInstance("Default")</code>.
+ * Please note that <code>Default</code> algorithm is supported as of Java 6.
+ * This method will fall back onto {@link #createDefault()} when
+ * <code>Default</code> algorithm is not available.
+ *
+ * @return default system SSL context
+ */
+ public static SSLContext createSystemDefault() throws SSLInitializationException {
+ try {
+ return SSLContext.getInstance("Default");
+ } catch (final NoSuchAlgorithmException ex) {
+ return createDefault();
+ }
+ }
+
+ /**
+ * Creates custom SSL context.
+ *
+ * @return default system SSL context
+ */
+ public static SSLContextBuilder custom() {
+ return new SSLContextBuilder();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLInitializationException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLInitializationException.java
new file mode 100644
index 000000000..98cb5f9c3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLInitializationException.java
@@ -0,0 +1,37 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+public class SSLInitializationException extends IllegalStateException {
+
+ private static final long serialVersionUID = -8243587425648536702L;
+
+ public SSLInitializationException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLSocketFactory.java
new file mode 100644
index 000000000..5c514d780
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLSocketFactory.java
@@ -0,0 +1,570 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress;
+import ch.boye.httpclientandroidlib.conn.scheme.HostNameResolver;
+import ch.boye.httpclientandroidlib.conn.scheme.LayeredSchemeSocketFactory;
+import ch.boye.httpclientandroidlib.conn.scheme.LayeredSocketFactory;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeLayeredSocketFactory;
+import ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+/**
+ * Layered socket factory for TLS/SSL connections.
+ * <p>
+ * SSLSocketFactory can be used to validate the identity of the HTTPS server against a list of
+ * trusted certificates and to authenticate to the HTTPS server using a private key.
+ * <p>
+ * SSLSocketFactory will enable server authentication when supplied with
+ * a {@link KeyStore trust-store} file containing one or several trusted certificates. The client
+ * secure socket will reject the connection during the SSL session handshake if the target HTTPS
+ * server attempts to authenticate itself with a non-trusted certificate.
+ * <p>
+ * Use JDK keytool utility to import a trusted certificate and generate a trust-store file:
+ * <pre>
+ * keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
+ * </pre>
+ * <p>
+ * In special cases the standard trust verification process can be bypassed by using a custom
+ * {@link TrustStrategy}. This interface is primarily intended for allowing self-signed
+ * certificates to be accepted as trusted without having to add them to the trust-store file.
+ * <p>
+ * SSLSocketFactory will enable client authentication when supplied with
+ * a {@link KeyStore key-store} file containing a private key/public certificate
+ * pair. The client secure socket will use the private key to authenticate
+ * itself to the target HTTPS server during the SSL session handshake if
+ * requested to do so by the server.
+ * The target HTTPS server will in its turn verify the certificate presented
+ * by the client in order to establish client's authenticity.
+ * <p>
+ * Use the following sequence of actions to generate a key-store file
+ * </p>
+ * <ul>
+ * <li>
+ * <p>
+ * Use JDK keytool utility to generate a new key
+ * <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
+ * For simplicity use the same password for the key as that of the key-store
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Issue a certificate signing request (CSR)
+ * <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Send the certificate request to the trusted Certificate Authority for signature.
+ * One may choose to act as her own CA and sign the certificate request using a PKI
+ * tool, such as OpenSSL.
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Import the trusted CA root certificate
+ * <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Import the PKCS#7 file containg the complete certificate chain
+ * <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Verify the content the resultant keystore file
+ * <pre>keytool -list -v -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link SSLConnectionSocketFactory}.
+ */
+@ThreadSafe
+@Deprecated
+public class SSLSocketFactory implements LayeredConnectionSocketFactory, SchemeLayeredSocketFactory,
+ LayeredSchemeSocketFactory, LayeredSocketFactory {
+
+ public static final String TLS = "TLS";
+ public static final String SSL = "SSL";
+ public static final String SSLV2 = "SSLv2";
+
+ public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER
+ = new AllowAllHostnameVerifier();
+
+ public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
+ = new BrowserCompatHostnameVerifier();
+
+ public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER
+ = new StrictHostnameVerifier();
+
+ /**
+ * Obtains default SSL socket factory with an SSL context based on the standard JSSE
+ * trust material (<code>cacerts</code> file in the security properties directory).
+ * System properties are not taken into consideration.
+ *
+ * @return default SSL socket factory
+ */
+ public static SSLSocketFactory getSocketFactory() throws SSLInitializationException {
+ return new SSLSocketFactory(
+ SSLContexts.createDefault(),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ private static String[] split(final String s) {
+ if (TextUtils.isBlank(s)) {
+ return null;
+ }
+ return s.split(" *, *");
+ }
+
+ /**
+ * Obtains default SSL socket factory with an SSL context based on system properties
+ * as described in
+ * <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html">
+ * "JavaTM Secure Socket Extension (JSSE) Reference Guide for the JavaTM 2 Platform
+ * Standard Edition 5</a>
+ *
+ * @return default system SSL socket factory
+ */
+ public static SSLSocketFactory getSystemSocketFactory() throws SSLInitializationException {
+ return new SSLSocketFactory(
+ (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault(),
+ split(System.getProperty("https.protocols")),
+ split(System.getProperty("https.cipherSuites")),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ private final javax.net.ssl.SSLSocketFactory socketfactory;
+ private final HostNameResolver nameResolver;
+ // TODO: make final
+ private volatile X509HostnameVerifier hostnameVerifier;
+ private final String[] supportedProtocols;
+ private final String[] supportedCipherSuites;
+
+ public SSLSocketFactory(
+ final String algorithm,
+ final KeyStore keystore,
+ final String keyPassword,
+ final KeyStore truststore,
+ final SecureRandom random,
+ final HostNameResolver nameResolver)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ this(SSLContexts.custom()
+ .useProtocol(algorithm)
+ .setSecureRandom(random)
+ .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
+ .loadTrustMaterial(truststore)
+ .build(),
+ nameResolver);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public SSLSocketFactory(
+ final String algorithm,
+ final KeyStore keystore,
+ final String keyPassword,
+ final KeyStore truststore,
+ final SecureRandom random,
+ final TrustStrategy trustStrategy,
+ final X509HostnameVerifier hostnameVerifier)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ this(SSLContexts.custom()
+ .useProtocol(algorithm)
+ .setSecureRandom(random)
+ .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
+ .loadTrustMaterial(truststore, trustStrategy)
+ .build(),
+ hostnameVerifier);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public SSLSocketFactory(
+ final String algorithm,
+ final KeyStore keystore,
+ final String keyPassword,
+ final KeyStore truststore,
+ final SecureRandom random,
+ final X509HostnameVerifier hostnameVerifier)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ this(SSLContexts.custom()
+ .useProtocol(algorithm)
+ .setSecureRandom(random)
+ .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
+ .loadTrustMaterial(truststore)
+ .build(),
+ hostnameVerifier);
+ }
+
+ public SSLSocketFactory(
+ final KeyStore keystore,
+ final String keystorePassword,
+ final KeyStore truststore)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ this(SSLContexts.custom()
+ .loadKeyMaterial(keystore, keystorePassword != null ? keystorePassword.toCharArray() : null)
+ .loadTrustMaterial(truststore)
+ .build(),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ public SSLSocketFactory(
+ final KeyStore keystore,
+ final String keystorePassword)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException{
+ this(SSLContexts.custom()
+ .loadKeyMaterial(keystore, keystorePassword != null ? keystorePassword.toCharArray() : null)
+ .build(),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ public SSLSocketFactory(
+ final KeyStore truststore)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ this(SSLContexts.custom()
+ .loadTrustMaterial(truststore)
+ .build(),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public SSLSocketFactory(
+ final TrustStrategy trustStrategy,
+ final X509HostnameVerifier hostnameVerifier)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ this(SSLContexts.custom()
+ .loadTrustMaterial(null, trustStrategy)
+ .build(),
+ hostnameVerifier);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public SSLSocketFactory(
+ final TrustStrategy trustStrategy)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ this(SSLContexts.custom()
+ .loadTrustMaterial(null, trustStrategy)
+ .build(),
+ BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ public SSLSocketFactory(final SSLContext sslContext) {
+ this(sslContext, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ }
+
+ public SSLSocketFactory(
+ final SSLContext sslContext, final HostNameResolver nameResolver) {
+ super();
+ this.socketfactory = sslContext.getSocketFactory();
+ this.hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+ this.nameResolver = nameResolver;
+ this.supportedProtocols = null;
+ this.supportedCipherSuites = null;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public SSLSocketFactory(
+ final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) {
+ this(Args.notNull(sslContext, "SSL context").getSocketFactory(),
+ null, null, hostnameVerifier);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public SSLSocketFactory(
+ final SSLContext sslContext,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final X509HostnameVerifier hostnameVerifier) {
+ this(Args.notNull(sslContext, "SSL context").getSocketFactory(),
+ supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public SSLSocketFactory(
+ final javax.net.ssl.SSLSocketFactory socketfactory,
+ final X509HostnameVerifier hostnameVerifier) {
+ this(socketfactory, null, null, hostnameVerifier);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public SSLSocketFactory(
+ final javax.net.ssl.SSLSocketFactory socketfactory,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final X509HostnameVerifier hostnameVerifier) {
+ this.socketfactory = Args.notNull(socketfactory, "SSL socket factory");
+ this.supportedProtocols = supportedProtocols;
+ this.supportedCipherSuites = supportedCipherSuites;
+ this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+ this.nameResolver = null;
+ }
+
+ /**
+ * @param params Optional parameters. Parameters passed to this method will have no effect.
+ * This method will create a unconnected instance of {@link Socket} class.
+ * @since 4.1
+ */
+ public Socket createSocket(final HttpParams params) throws IOException {
+ return createSocket((HttpContext) null);
+ }
+
+ public Socket createSocket() throws IOException {
+ return createSocket((HttpContext) null);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public Socket connectSocket(
+ final Socket socket,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
+ Args.notNull(remoteAddress, "Remote address");
+ Args.notNull(params, "HTTP parameters");
+ final HttpHost host;
+ if (remoteAddress instanceof HttpInetSocketAddress) {
+ host = ((HttpInetSocketAddress) remoteAddress).getHttpHost();
+ } else {
+ host = new HttpHost(remoteAddress.getHostName(), remoteAddress.getPort(), "https");
+ }
+ final int socketTimeout = HttpConnectionParams.getSoTimeout(params);
+ final int connectTimeout = HttpConnectionParams.getConnectionTimeout(params);
+ socket.setSoTimeout(socketTimeout);
+ return connectSocket(connectTimeout, socket, host, remoteAddress, localAddress, null);
+ }
+
+ /**
+ * Checks whether a socket connection is secure.
+ * This factory creates TLS/SSL socket connections
+ * which, by default, are considered secure.
+ * <br/>
+ * Derived classes may override this method to perform
+ * runtime checks, for example based on the cypher suite.
+ *
+ * @param sock the connected socket
+ *
+ * @return <code>true</code>
+ *
+ * @throws IllegalArgumentException if the argument is invalid
+ */
+ public boolean isSecure(final Socket sock) throws IllegalArgumentException {
+ Args.notNull(sock, "Socket");
+ Asserts.check(sock instanceof SSLSocket, "Socket not created by this factory");
+ Asserts.check(!sock.isClosed(), "Socket is closed");
+ return true;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String host,
+ final int port,
+ final HttpParams params) throws IOException, UnknownHostException {
+ return createLayeredSocket(socket, host, port, (HttpContext) null);
+ }
+
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String host,
+ final int port,
+ final boolean autoClose) throws IOException, UnknownHostException {
+ return createLayeredSocket(socket, host, port, (HttpContext) null);
+ }
+
+ public void setHostnameVerifier(final X509HostnameVerifier hostnameVerifier) {
+ Args.notNull(hostnameVerifier, "Hostname verifier");
+ this.hostnameVerifier = hostnameVerifier;
+ }
+
+ public X509HostnameVerifier getHostnameVerifier() {
+ return this.hostnameVerifier;
+ }
+
+ public Socket connectSocket(
+ final Socket socket,
+ final String host, final int port,
+ final InetAddress local, final int localPort,
+ final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
+ final InetAddress remote;
+ if (this.nameResolver != null) {
+ remote = this.nameResolver.resolve(host);
+ } else {
+ remote = InetAddress.getByName(host);
+ }
+ InetSocketAddress localAddress = null;
+ if (local != null || localPort > 0) {
+ localAddress = new InetSocketAddress(local, localPort > 0 ? localPort : 0);
+ }
+ final InetSocketAddress remoteAddress = new HttpInetSocketAddress(
+ new HttpHost(host, port), remote, port);
+ return connectSocket(socket, remoteAddress, localAddress, params);
+ }
+
+ public Socket createSocket(
+ final Socket socket,
+ final String host, final int port,
+ final boolean autoClose) throws IOException, UnknownHostException {
+ return createLayeredSocket(socket, host, port, autoClose);
+ }
+
+ /**
+ * Performs any custom initialization for a newly created SSLSocket
+ * (before the SSL handshake happens).
+ *
+ * The default implementation is a no-op, but could be overridden to, e.g.,
+ * call {@link SSLSocket#setEnabledCipherSuites(java.lang.String[])}.
+ *
+ * @since 4.2
+ */
+ protected void prepareSocket(final SSLSocket socket) throws IOException {
+ }
+
+ private void internalPrepareSocket(final SSLSocket socket) throws IOException {
+ if (supportedProtocols != null) {
+ socket.setEnabledProtocols(supportedProtocols);
+ }
+ if (supportedCipherSuites != null) {
+ socket.setEnabledCipherSuites(supportedCipherSuites);
+ }
+ prepareSocket(socket);
+ }
+
+ public Socket createSocket(final HttpContext context) throws IOException {
+ final SSLSocket sock = (SSLSocket) this.socketfactory.createSocket();
+ internalPrepareSocket(sock);
+ return sock;
+ }
+
+ public Socket connectSocket(
+ final int connectTimeout,
+ final Socket socket,
+ final HttpHost host,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final HttpContext context) throws IOException {
+ Args.notNull(host, "HTTP host");
+ Args.notNull(remoteAddress, "Remote address");
+ final Socket sock = socket != null ? socket : createSocket(context);
+ if (localAddress != null) {
+ sock.bind(localAddress);
+ }
+ try {
+ sock.connect(remoteAddress, connectTimeout);
+ } catch (final IOException ex) {
+ try {
+ sock.close();
+ } catch (final IOException ignore) {
+ }
+ throw ex;
+ }
+ // Setup SSL layering if necessary
+ if (sock instanceof SSLSocket) {
+ final SSLSocket sslsock = (SSLSocket) sock;
+ sslsock.startHandshake();
+ verifyHostname(sslsock, host.getHostName());
+ return sock;
+ } else {
+ return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context);
+ }
+ }
+
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target,
+ final int port,
+ final HttpContext context) throws IOException {
+ final SSLSocket sslsock = (SSLSocket) this.socketfactory.createSocket(
+ socket,
+ target,
+ port,
+ true);
+ internalPrepareSocket(sslsock);
+ sslsock.startHandshake();
+ verifyHostname(sslsock, target);
+ return sslsock;
+ }
+
+ private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException {
+ try {
+ this.hostnameVerifier.verify(hostname, sslsock);
+ // verifyHostName() didn't blowup - good!
+ } catch (final IOException iox) {
+ // close the socket before re-throwing the exception
+ try { sslsock.close(); } catch (final Exception x) { /*ignore*/ }
+ throw iox;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java
new file mode 100644
index 000000000..a6328a10c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import javax.net.ssl.SSLException;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * The Strict HostnameVerifier works the same way as Sun Java 1.4, Sun
+ * Java 5, Sun Java 6-rc. It's also pretty close to IE6. This
+ * implementation appears to be compliant with RFC 2818 for dealing with
+ * wildcards.
+ * <p/>
+ * The hostname must match either the first CN, or any of the subject-alts.
+ * A wildcard can occur in the CN, and in any of the subject-alts. The
+ * one divergence from IE6 is how we only check the first CN. IE6 allows
+ * a match against any of the CNs present. We decided to follow in
+ * Sun Java 1.4's footsteps and only check the first CN. (If you need
+ * to check all the CN's, feel free to write your own implementation!).
+ * <p/>
+ * A wildcard such as "*.foo.com" matches only subdomains in the same
+ * level, for example "a.foo.com". It does not match deeper subdomains
+ * such as "a.b.foo.com".
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class StrictHostnameVerifier extends AbstractVerifier {
+
+ public final void verify(
+ final String host,
+ final String[] cns,
+ final String[] subjectAlts) throws SSLException {
+ verify(host, cns, subjectAlts, true);
+ }
+
+ @Override
+ public final String toString() {
+ return "STRICT";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TokenParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TokenParser.java
new file mode 100644
index 000000000..25bdcc5e6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TokenParser.java
@@ -0,0 +1,266 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.util.BitSet;
+
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Low level parser for header field elements. The parsing routines of this class are designed
+ * to produce near zero intermediate garbage and make no intermediate copies of input data.
+ * <p>
+ * This class is immutable and thread safe.
+ *
+ * Temporary package-private copy of ch.boye.httpclientandroidlib.message.TokenParser
+ */
+class TokenParser {
+
+ public static BitSet INIT_BITSET(final int ... b) {
+ final BitSet bitset = new BitSet();
+ for (final int aB : b) {
+ bitset.set(aB);
+ }
+ return bitset;
+ }
+
+ /** US-ASCII CR, carriage return (13) */
+ public static final char CR = '\r';
+
+ /** US-ASCII LF, line feed (10) */
+ public static final char LF = '\n';
+
+ /** US-ASCII SP, space (32) */
+ public static final char SP = ' ';
+
+ /** US-ASCII HT, horizontal-tab (9) */
+ public static final char HT = '\t';
+
+ /** Double quote */
+ public static final char DQUOTE = '\"';
+
+ /** Backward slash / escape character */
+ public static final char ESCAPE = '\\';
+
+ public static boolean isWhitespace(final char ch) {
+ return ch == SP || ch == HT || ch == CR || ch == LF;
+ }
+
+ public static final TokenParser INSTANCE = new TokenParser();
+
+ /**
+ * Extracts from the sequence of chars a token terminated with any of the given delimiters
+ * discarding semantically insignificant whitespace characters.
+ *
+ * @param buf buffer with the sequence of chars to be parsed
+ * @param cursor defines the bounds and current position of the buffer
+ * @param delimiters set of delimiting characters. Can be <code>null</code> if the token
+ * is not delimited by any character.
+ */
+ public String parseToken(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) {
+ final StringBuilder dst = new StringBuilder();
+ boolean whitespace = false;
+ while (!cursor.atEnd()) {
+ final char current = buf.charAt(cursor.getPos());
+ if (delimiters != null && delimiters.get(current)) {
+ break;
+ } else if (isWhitespace(current)) {
+ skipWhiteSpace(buf, cursor);
+ whitespace = true;
+ } else {
+ if (whitespace && dst.length() > 0) {
+ dst.append(' ');
+ }
+ copyContent(buf, cursor, delimiters, dst);
+ whitespace = false;
+ }
+ }
+ return dst.toString();
+ }
+
+ /**
+ * Extracts from the sequence of chars a value which can be enclosed in quote marks and
+ * terminated with any of the given delimiters discarding semantically insignificant
+ * whitespace characters.
+ *
+ * @param buf buffer with the sequence of chars to be parsed
+ * @param cursor defines the bounds and current position of the buffer
+ * @param delimiters set of delimiting characters. Can be <code>null</code> if the value
+ * is not delimited by any character.
+ */
+ public String parseValue(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) {
+ final StringBuilder dst = new StringBuilder();
+ boolean whitespace = false;
+ while (!cursor.atEnd()) {
+ final char current = buf.charAt(cursor.getPos());
+ if (delimiters != null && delimiters.get(current)) {
+ break;
+ } else if (isWhitespace(current)) {
+ skipWhiteSpace(buf, cursor);
+ whitespace = true;
+ } else if (current == DQUOTE) {
+ if (whitespace && dst.length() > 0) {
+ dst.append(' ');
+ }
+ copyQuotedContent(buf, cursor, dst);
+ whitespace = false;
+ } else {
+ if (whitespace && dst.length() > 0) {
+ dst.append(' ');
+ }
+ copyUnquotedContent(buf, cursor, delimiters, dst);
+ whitespace = false;
+ }
+ }
+ return dst.toString();
+ }
+
+ /**
+ * Skips semantically insignificant whitespace characters and moves the cursor to the closest
+ * non-whitespace character.
+ *
+ * @param buf buffer with the sequence of chars to be parsed
+ * @param cursor defines the bounds and current position of the buffer
+ */
+ public void skipWhiteSpace(final CharArrayBuffer buf, final ParserCursor cursor) {
+ int pos = cursor.getPos();
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+ for (int i = indexFrom; i < indexTo; i++) {
+ final char current = buf.charAt(i);
+ if (!isWhitespace(current)) {
+ break;
+ } else {
+ pos++;
+ }
+ }
+ cursor.updatePos(pos);
+ }
+
+ /**
+ * Transfers content into the destination buffer until a whitespace character or any of
+ * the given delimiters is encountered.
+ *
+ * @param buf buffer with the sequence of chars to be parsed
+ * @param cursor defines the bounds and current position of the buffer
+ * @param delimiters set of delimiting characters. Can be <code>null</code> if the value
+ * is delimited by a whitespace only.
+ * @param dst destination buffer
+ */
+ public void copyContent(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters,
+ final StringBuilder dst) {
+ int pos = cursor.getPos();
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+ for (int i = indexFrom; i < indexTo; i++) {
+ final char current = buf.charAt(i);
+ if ((delimiters != null && delimiters.get(current)) || isWhitespace(current)) {
+ break;
+ } else {
+ pos++;
+ dst.append(current);
+ }
+ }
+ cursor.updatePos(pos);
+ }
+
+ /**
+ * Transfers content into the destination buffer until a whitespace character, a quote,
+ * or any of the given delimiters is encountered.
+ *
+ * @param buf buffer with the sequence of chars to be parsed
+ * @param cursor defines the bounds and current position of the buffer
+ * @param delimiters set of delimiting characters. Can be <code>null</code> if the value
+ * is delimited by a whitespace or a quote only.
+ * @param dst destination buffer
+ */
+ public void copyUnquotedContent(final CharArrayBuffer buf, final ParserCursor cursor,
+ final BitSet delimiters, final StringBuilder dst) {
+ int pos = cursor.getPos();
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+ for (int i = indexFrom; i < indexTo; i++) {
+ final char current = buf.charAt(i);
+ if ((delimiters != null && delimiters.get(current))
+ || isWhitespace(current) || current == DQUOTE) {
+ break;
+ } else {
+ pos++;
+ dst.append(current);
+ }
+ }
+ cursor.updatePos(pos);
+ }
+
+ /**
+ * Transfers content enclosed with quote marks into the destination buffer.
+ *
+ * @param buf buffer with the sequence of chars to be parsed
+ * @param cursor defines the bounds and current position of the buffer
+ * @param dst destination buffer
+ */
+ public void copyQuotedContent(final CharArrayBuffer buf, final ParserCursor cursor,
+ final StringBuilder dst) {
+ if (cursor.atEnd()) {
+ return;
+ }
+ int pos = cursor.getPos();
+ int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+ char current = buf.charAt(pos);
+ if (current != DQUOTE) {
+ return;
+ }
+ pos++;
+ indexFrom++;
+ boolean escaped = false;
+ for (int i = indexFrom; i < indexTo; i++, pos++) {
+ current = buf.charAt(i);
+ if (escaped) {
+ if (current != DQUOTE && current != ESCAPE) {
+ dst.append(ESCAPE);
+ }
+ dst.append(current);
+ escaped = false;
+ } else {
+ if (current == DQUOTE) {
+ pos++;
+ break;
+ }
+ if (current == ESCAPE) {
+ escaped = true;
+ } else if (current != CR && current != LF) {
+ dst.append(current);
+ }
+ }
+ }
+ cursor.updatePos(pos);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java
new file mode 100644
index 000000000..a3c23690b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java
@@ -0,0 +1,45 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ * A trust strategy that accepts self-signed certificates as trusted. Verification of all other
+ * certificates is done by the trust manager configured in the SSL context.
+ *
+ * @since 4.1
+ */
+public class TrustSelfSignedStrategy implements TrustStrategy {
+
+ public boolean isTrusted(
+ final X509Certificate[] chain, final String authType) throws CertificateException {
+ return chain.length == 1;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustStrategy.java
new file mode 100644
index 000000000..7f4914503
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ * A strategy to establish trustworthiness of certificates without consulting the trust manager
+ * configured in the actual SSL context. This interface can be used to override the standard
+ * JSSE certificate verification process.
+ *
+ * @since 4.1
+ */
+public interface TrustStrategy {
+
+ /**
+ * Determines whether the certificate chain can be trusted without consulting the trust manager
+ * configured in the actual SSL context. This method can be used to override the standard JSSE
+ * certificate verification process.
+ * <p>
+ * Please note that, if this method returns <code>false</code>, the trust manager configured
+ * in the actual SSL context can still clear the certificate as trusted.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the authentication type based on the client certificate
+ * @return <code>true</code> if the certificate can be trusted without verification by
+ * the trust manager, <code>false</code> otherwise.
+ * @throws CertificateException thrown if the certificate is not trusted or invalid.
+ */
+ boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java
new file mode 100644
index 000000000..cd57c623e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java
@@ -0,0 +1,85 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.ssl;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocket;
+
+/**
+ * Interface for checking if a hostname matches the names stored inside the
+ * server's X.509 certificate. This interface extends
+ * {@link javax.net.ssl.HostnameVerifier}, but it is recommended to use
+ * methods added by X509HostnameVerifier.
+ *
+ * @since 4.0
+ */
+public interface X509HostnameVerifier extends HostnameVerifier {
+
+ /**
+ * Verifies that the host name is an acceptable match with the server's
+ * authentication scheme based on the given {@link SSLSocket}.
+ *
+ * @param host the host.
+ * @param ssl the SSL socket.
+ * @throws IOException if an I/O error occurs or the verification process
+ * fails.
+ */
+ void verify(String host, SSLSocket ssl) throws IOException;
+
+ /**
+ * Verifies that the host name is an acceptable match with the server's
+ * authentication scheme based on the given {@link X509Certificate}.
+ *
+ * @param host the host.
+ * @param cert the certificate.
+ * @throws SSLException if the verification process fails.
+ */
+ void verify(String host, X509Certificate cert) throws SSLException;
+
+ /**
+ * Checks to see if the supplied hostname matches any of the supplied CNs
+ * or "DNS" Subject-Alts. Most implementations only look at the first CN,
+ * and ignore any additional CNs. Most implementations do look at all of
+ * the "DNS" Subject-Alts. The CNs or Subject-Alts may contain wildcards
+ * according to RFC 2818.
+ *
+ * @param cns CN fields, in order, as extracted from the X.509
+ * certificate.
+ * @param subjectAlts Subject-Alt fields of type 2 ("DNS"), as extracted
+ * from the X.509 certificate.
+ * @param host The hostname to verify.
+ * @throws SSLException if the verification process fails.
+ */
+ void verify(String host, String[] cns, String[] subjectAlts)
+ throws SSLException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/package-info.java
new file mode 100644
index 000000000..c05bf5be0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client TLS/SSL support.
+ */
+package ch.boye.httpclientandroidlib.conn.ssl;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/InetAddressUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/InetAddressUtils.java
new file mode 100644
index 000000000..ac9a8e2db
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/InetAddressUtils.java
@@ -0,0 +1,123 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.conn.util;
+
+import java.util.regex.Pattern;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * A collection of utilities relating to InetAddresses.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class InetAddressUtils {
+
+ private InetAddressUtils() {
+ }
+
+ private static final String IPV4_BASIC_PATTERN_STRING =
+ "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + // initial 3 fields, 0-255 followed by .
+ "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255
+
+ private static final Pattern IPV4_PATTERN =
+ Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$");
+
+ private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros
+ Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$");
+
+ private static final Pattern IPV6_STD_PATTERN =
+ Pattern.compile(
+ "^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$");
+
+ private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
+ Pattern.compile(
+ "^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields
+ "::" +
+ "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields
+
+ /*
+ * The above pattern is not totally rigorous as it allows for more than 7 hex fields in total
+ */
+ private static final char COLON_CHAR = ':';
+
+ // Must not have more than 7 colons (i.e. 8 fields)
+ private static final int MAX_COLON_COUNT = 7;
+
+ /**
+ * Checks whether the parameter is a valid IPv4 address
+ *
+ * @param input the address string to check for validity
+ * @return true if the input parameter is a valid IPv4 address
+ */
+ public static boolean isIPv4Address(final String input) {
+ return IPV4_PATTERN.matcher(input).matches();
+ }
+
+ public static boolean isIPv4MappedIPv64Address(final String input) {
+ return IPV4_MAPPED_IPV6_PATTERN.matcher(input).matches();
+ }
+
+ /**
+ * Checks whether the parameter is a valid standard (non-compressed) IPv6 address
+ *
+ * @param input the address string to check for validity
+ * @return true if the input parameter is a valid standard (non-compressed) IPv6 address
+ */
+ public static boolean isIPv6StdAddress(final String input) {
+ return IPV6_STD_PATTERN.matcher(input).matches();
+ }
+
+ /**
+ * Checks whether the parameter is a valid compressed IPv6 address
+ *
+ * @param input the address string to check for validity
+ * @return true if the input parameter is a valid compressed IPv6 address
+ */
+ public static boolean isIPv6HexCompressedAddress(final String input) {
+ int colonCount = 0;
+ for(int i = 0; i < input.length(); i++) {
+ if (input.charAt(i) == COLON_CHAR) {
+ colonCount++;
+ }
+ }
+ return colonCount <= MAX_COLON_COUNT && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
+ }
+
+ /**
+ * Checks whether the parameter is a valid IPv6 address (including compressed).
+ *
+ * @param input the address string to check for validity
+ * @return true if the input parameter is a valid standard or compressed IPv6 address
+ */
+ public static boolean isIPv6Address(final String input) {
+ return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/package-info.java
new file mode 100644
index 000000000..6db59b736
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Connection utility classes.
+ */
+package ch.boye.httpclientandroidlib.conn.util;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/ClientCookie.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/ClientCookie.java
new file mode 100644
index 000000000..1909f0999
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/ClientCookie.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+/**
+ * ClientCookie extends the standard {@link Cookie} interface with
+ * additional client specific functionality such ability to retrieve
+ * original cookie attributes exactly as they were specified by the
+ * origin server. This is important for generating the <tt>Cookie</tt>
+ * header because some cookie specifications require that the
+ * <tt>Cookie</tt> header should include certain attributes only if
+ * they were specified in the <tt>Set-Cookie</tt> header.
+ *
+ *
+ * @since 4.0
+ */
+public interface ClientCookie extends Cookie {
+
+ // RFC2109 attributes
+ public static final String VERSION_ATTR = "version";
+ public static final String PATH_ATTR = "path";
+ public static final String DOMAIN_ATTR = "domain";
+ public static final String MAX_AGE_ATTR = "max-age";
+ public static final String SECURE_ATTR = "secure";
+ public static final String COMMENT_ATTR = "comment";
+ public static final String EXPIRES_ATTR = "expires";
+
+ // RFC2965 attributes
+ public static final String PORT_ATTR = "port";
+ public static final String COMMENTURL_ATTR = "commenturl";
+ public static final String DISCARD_ATTR = "discard";
+
+ String getAttribute(String name);
+
+ boolean containsAttribute(String name);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/Cookie.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/Cookie.java
new file mode 100644
index 000000000..9953ab794
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/Cookie.java
@@ -0,0 +1,137 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import java.util.Date;
+
+/**
+ * Cookie interface represents a token or short packet of state information
+ * (also referred to as "magic-cookie") that the HTTP agent and the target
+ * server can exchange to maintain a session. In its simples form an HTTP
+ * cookie is merely a name / value pair.
+ *
+ * @since 4.0
+ */
+public interface Cookie {
+
+ /**
+ * Returns the name.
+ *
+ * @return String name The name
+ */
+ String getName();
+
+ /**
+ * Returns the value.
+ *
+ * @return String value The current value.
+ */
+ String getValue();
+
+ /**
+ * Returns the comment describing the purpose of this cookie, or
+ * <tt>null</tt> if no such comment has been defined.
+ *
+ * @return comment
+ */
+ String getComment();
+
+ /**
+ * If a user agent (web browser) presents this cookie to a user, the
+ * cookie's purpose will be described by the information at this URL.
+ */
+ String getCommentURL();
+
+ /**
+ * Returns the expiration {@link Date} of the cookie, or <tt>null</tt>
+ * if none exists.
+ * <p><strong>Note:</strong> the object returned by this method is
+ * considered immutable. Changing it (e.g. using setTime()) could result
+ * in undefined behaviour. Do so at your peril. </p>
+ * @return Expiration {@link Date}, or <tt>null</tt>.
+ */
+ Date getExpiryDate();
+
+ /**
+ * Returns <tt>false</tt> if the cookie should be discarded at the end
+ * of the "session"; <tt>true</tt> otherwise.
+ *
+ * @return <tt>false</tt> if the cookie should be discarded at the end
+ * of the "session"; <tt>true</tt> otherwise
+ */
+ boolean isPersistent();
+
+ /**
+ * Returns domain attribute of the cookie. The value of the Domain
+ * attribute specifies the domain for which the cookie is valid.
+ *
+ * @return the value of the domain attribute.
+ */
+ String getDomain();
+
+ /**
+ * Returns the path attribute of the cookie. The value of the Path
+ * attribute specifies the subset of URLs on the origin server to which
+ * this cookie applies.
+ *
+ * @return The value of the path attribute.
+ */
+ String getPath();
+
+ /**
+ * Get the Port attribute. It restricts the ports to which a cookie
+ * may be returned in a Cookie request header.
+ */
+ int[] getPorts();
+
+ /**
+ * Indicates whether this cookie requires a secure connection.
+ *
+ * @return <code>true</code> if this cookie should only be sent
+ * over secure connections, <code>false</code> otherwise.
+ */
+ boolean isSecure();
+
+ /**
+ * Returns the version of the cookie specification to which this
+ * cookie conforms.
+ *
+ * @return the version of the cookie.
+ */
+ int getVersion();
+
+ /**
+ * Returns true if this cookie has expired.
+ * @param date Current time
+ *
+ * @return <tt>true</tt> if the cookie has expired.
+ */
+ boolean isExpired(final Date date);
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieAttributeHandler.java
new file mode 100644
index 000000000..3d94c8a6f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieAttributeHandler.java
@@ -0,0 +1,73 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.cookie;
+
+/**
+ * This interface represents a cookie attribute handler responsible
+ * for parsing, validating, and matching a specific cookie attribute,
+ * such as path, domain, port, etc.
+ *
+ * Different cookie specifications can provide a specific
+ * implementation for this class based on their cookie handling
+ * rules.
+ *
+ *
+ * @since 4.0
+ */
+public interface CookieAttributeHandler {
+
+ /**
+ * Parse the given cookie attribute value and update the corresponding
+ * {@link ch.boye.httpclientandroidlib.cookie.Cookie} property.
+ *
+ * @param cookie {@link ch.boye.httpclientandroidlib.cookie.Cookie} to be updated
+ * @param value cookie attribute value from the cookie response header
+ */
+ void parse(SetCookie cookie, String value)
+ throws MalformedCookieException;
+
+ /**
+ * Peforms cookie validation for the given attribute value.
+ *
+ * @param cookie {@link ch.boye.httpclientandroidlib.cookie.Cookie} to validate
+ * @param origin the cookie source to validate against
+ * @throws MalformedCookieException if cookie validation fails for this attribute
+ */
+ void validate(Cookie cookie, CookieOrigin origin)
+ throws MalformedCookieException;
+
+ /**
+ * Matches the given value (property of the destination host where request is being
+ * submitted) with the corresponding cookie attribute.
+ *
+ * @param cookie {@link ch.boye.httpclientandroidlib.cookie.Cookie} to match
+ * @param origin the cookie source to match against
+ * @return <tt>true</tt> if the match is successful; <tt>false</tt> otherwise
+ */
+ boolean match(Cookie cookie, CookieOrigin origin);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieIdentityComparator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieIdentityComparator.java
new file mode 100644
index 000000000..863640e69
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieIdentityComparator.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * This cookie comparator can be used to compare identity of cookies.
+ * <p>
+ * Cookies are considered identical if their names are equal and
+ * their domain attributes match ignoring case.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class CookieIdentityComparator implements Serializable, Comparator<Cookie> {
+
+ private static final long serialVersionUID = 4466565437490631532L;
+
+ public int compare(final Cookie c1, final Cookie c2) {
+ int res = c1.getName().compareTo(c2.getName());
+ if (res == 0) {
+ // do not differentiate empty and null domains
+ String d1 = c1.getDomain();
+ if (d1 == null) {
+ d1 = "";
+ } else if (d1.indexOf('.') == -1) {
+ d1 = d1 + ".local";
+ }
+ String d2 = c2.getDomain();
+ if (d2 == null) {
+ d2 = "";
+ } else if (d2.indexOf('.') == -1) {
+ d2 = d2 + ".local";
+ }
+ res = d1.compareToIgnoreCase(d2);
+ }
+ if (res == 0) {
+ String p1 = c1.getPath();
+ if (p1 == null) {
+ p1 = "/";
+ }
+ String p2 = c2.getPath();
+ if (p2 == null) {
+ p2 = "/";
+ }
+ res = p1.compareTo(p2);
+ }
+ return res;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieOrigin.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieOrigin.java
new file mode 100644
index 000000000..aef29023d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieOrigin.java
@@ -0,0 +1,94 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.cookie;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * CookieOrigin class encapsulates details of an origin server that
+ * are relevant when parsing, validating or matching HTTP cookies.
+ *
+ * @since 4.0
+ */
+@Immutable
+public final class CookieOrigin {
+
+ private final String host;
+ private final int port;
+ private final String path;
+ private final boolean secure;
+
+ public CookieOrigin(final String host, final int port, final String path, final boolean secure) {
+ super();
+ Args.notBlank(host, "Host");
+ Args.notNegative(port, "Port");
+ Args.notNull(path, "Path");
+ this.host = host.toLowerCase(Locale.ENGLISH);
+ this.port = port;
+ if (path.trim().length() != 0) {
+ this.path = path;
+ } else {
+ this.path = "/";
+ }
+ this.secure = secure;
+ }
+
+ public String getHost() {
+ return this.host;
+ }
+
+ public String getPath() {
+ return this.path;
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ public boolean isSecure() {
+ return this.secure;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append('[');
+ if (this.secure) {
+ buffer.append("(secure)");
+ }
+ buffer.append(this.host);
+ buffer.append(':');
+ buffer.append(Integer.toString(this.port));
+ buffer.append(this.path);
+ buffer.append(']');
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookiePathComparator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookiePathComparator.java
new file mode 100644
index 000000000..984bb850f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookiePathComparator.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * This cookie comparator ensures that multiple cookies satisfying
+ * a common criteria are ordered in the <tt>Cookie</tt> header such
+ * that those with more specific Path attributes precede those with
+ * less specific.
+ *
+ * <p>
+ * This comparator assumes that Path attributes of two cookies
+ * path-match a commmon request-URI. Otherwise, the result of the
+ * comparison is undefined.
+ * </p>
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class CookiePathComparator implements Serializable, Comparator<Cookie> {
+
+ private static final long serialVersionUID = 7523645369616405818L;
+
+ private String normalizePath(final Cookie cookie) {
+ String path = cookie.getPath();
+ if (path == null) {
+ path = "/";
+ }
+ if (!path.endsWith("/")) {
+ path = path + '/';
+ }
+ return path;
+ }
+
+ public int compare(final Cookie c1, final Cookie c2) {
+ final String path1 = normalizePath(c1);
+ final String path2 = normalizePath(c2);
+ if (path1.equals(path2)) {
+ return 0;
+ } else if (path1.startsWith(path2)) {
+ return -1;
+ } else if (path2.startsWith(path1)) {
+ return 1;
+ } else {
+ // Does not really matter
+ return 0;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieRestrictionViolationException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieRestrictionViolationException.java
new file mode 100644
index 000000000..1e3f2d70c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieRestrictionViolationException.java
@@ -0,0 +1,61 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals that a cookie violates a restriction imposed by the cookie
+ * specification.
+ *
+ * @since 4.1
+ */
+@Immutable
+public class CookieRestrictionViolationException extends MalformedCookieException {
+
+ private static final long serialVersionUID = 7371235577078589013L;
+
+ /**
+ * Creates a new CookeFormatViolationException with a <tt>null</tt> detail
+ * message.
+ */
+ public CookieRestrictionViolationException() {
+ super();
+ }
+
+ /**
+ * Creates a new CookeRestrictionViolationException with a specified
+ * message string.
+ *
+ * @param message The exception detail message
+ */
+ public CookieRestrictionViolationException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpec.java
new file mode 100644
index 000000000..c222e5e72
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpec.java
@@ -0,0 +1,109 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Header;
+
+/**
+ * Defines the cookie management specification.
+ * <p>Cookie management specification must define
+ * <ul>
+ * <li> rules of parsing "Set-Cookie" header
+ * <li> rules of validation of parsed cookies
+ * <li> formatting of "Cookie" header
+ * </ul>
+ * for a given host, port and path of origin
+ *
+ *
+ * @since 4.0
+ */
+public interface CookieSpec {
+
+ /**
+ * Returns version of the state management this cookie specification
+ * conforms to.
+ *
+ * @return version of the state management specification
+ */
+ int getVersion();
+
+ /**
+ * Parse the <tt>"Set-Cookie"</tt> Header into an array of Cookies.
+ *
+ * <p>This method will not perform the validation of the resultant
+ * {@link Cookie}s</p>
+ *
+ * @see #validate
+ *
+ * @param header the <tt>Set-Cookie</tt> received from the server
+ * @param origin details of the cookie origin
+ * @return an array of <tt>Cookie</tt>s parsed from the header
+ * @throws MalformedCookieException if an exception occurs during parsing
+ */
+ List<Cookie> parse(Header header, CookieOrigin origin) throws MalformedCookieException;
+
+ /**
+ * Validate the cookie according to validation rules defined by the
+ * cookie specification.
+ *
+ * @param cookie the Cookie to validate
+ * @param origin details of the cookie origin
+ * @throws MalformedCookieException if the cookie is invalid
+ */
+ void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException;
+
+ /**
+ * Determines if a Cookie matches the target location.
+ *
+ * @param cookie the Cookie to be matched
+ * @param origin the target to test against
+ *
+ * @return <tt>true</tt> if the cookie should be submitted with a request
+ * with given attributes, <tt>false</tt> otherwise.
+ */
+ boolean match(Cookie cookie, CookieOrigin origin);
+
+ /**
+ * Create <tt>"Cookie"</tt> headers for an array of Cookies.
+ *
+ * @param cookies the Cookies format into a Cookie header
+ * @return a Header for the given Cookies.
+ * @throws IllegalArgumentException if an input parameter is illegal
+ */
+ List<Header> formatCookies(List<Cookie> cookies);
+
+ /**
+ * Returns a request header identifying what version of the state management
+ * specification is understood. May be <code>null</code> if the cookie
+ * specification does not support <tt>Cookie2</tt> header.
+ */
+ Header getVersionHeader();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecFactory.java
new file mode 100644
index 000000000..fd7851626
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecFactory.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * Factory for {@link CookieSpec} implementations.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link CookieSpecProvider}
+ */
+@Deprecated
+public interface CookieSpecFactory {
+
+ /**
+ * Creates an instance of {@link CookieSpec} using given HTTP parameters.
+ *
+ * @param params HTTP parameters.
+ *
+ * @return cookie spec.
+ */
+ CookieSpec newInstance(HttpParams params);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecProvider.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecProvider.java
new file mode 100644
index 000000000..921adfba4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecProvider.java
@@ -0,0 +1,46 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Factory for {@link CookieSpec} implementations.
+ *
+ * @since 4.3
+ */
+public interface CookieSpecProvider {
+
+ /**
+ * Creates an instance of {@link CookieSpec}.
+ *
+ * @return auth scheme.
+ */
+ CookieSpec create(HttpContext context);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecRegistry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecRegistry.java
new file mode 100644
index 000000000..adbfe863a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/CookieSpecRegistry.java
@@ -0,0 +1,167 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Cookie specification registry that can be used to obtain the corresponding
+ * cookie specification implementation for a given type of type or version of
+ * cookie.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.config.Registry}.
+ */
+@ThreadSafe
+@Deprecated
+public final class CookieSpecRegistry implements Lookup<CookieSpecProvider> {
+
+ private final ConcurrentHashMap<String,CookieSpecFactory> registeredSpecs;
+
+ public CookieSpecRegistry() {
+ super();
+ this.registeredSpecs = new ConcurrentHashMap<String,CookieSpecFactory>();
+ }
+
+ /**
+ * Registers a {@link CookieSpecFactory} with the given identifier.
+ * If a specification with the given name already exists it will be overridden.
+ * This nameis the same one used to retrieve the {@link CookieSpecFactory}
+ * from {@link #getCookieSpec(String)}.
+ *
+ * @param name the identifier for this specification
+ * @param factory the {@link CookieSpecFactory} class to register
+ *
+ * @see #getCookieSpec(String)
+ */
+ public void register(final String name, final CookieSpecFactory factory) {
+ Args.notNull(name, "Name");
+ Args.notNull(factory, "Cookie spec factory");
+ registeredSpecs.put(name.toLowerCase(Locale.ENGLISH), factory);
+ }
+
+ /**
+ * Unregisters the {@link CookieSpecFactory} with the given ID.
+ *
+ * @param id the identifier of the {@link CookieSpec cookie specification} to unregister
+ */
+ public void unregister(final String id) {
+ Args.notNull(id, "Id");
+ registeredSpecs.remove(id.toLowerCase(Locale.ENGLISH));
+ }
+
+ /**
+ * Gets the {@link CookieSpec cookie specification} with the given ID.
+ *
+ * @param name the {@link CookieSpec cookie specification} identifier
+ * @param params the {@link HttpParams HTTP parameters} for the cookie
+ * specification.
+ *
+ * @return {@link CookieSpec cookie specification}
+ *
+ * @throws IllegalStateException if a policy with the given name cannot be found
+ */
+ public CookieSpec getCookieSpec(final String name, final HttpParams params)
+ throws IllegalStateException {
+
+ Args.notNull(name, "Name");
+ final CookieSpecFactory factory = registeredSpecs.get(name.toLowerCase(Locale.ENGLISH));
+ if (factory != null) {
+ return factory.newInstance(params);
+ } else {
+ throw new IllegalStateException("Unsupported cookie spec: " + name);
+ }
+ }
+
+ /**
+ * Gets the {@link CookieSpec cookie specification} with the given name.
+ *
+ * @param name the {@link CookieSpec cookie specification} identifier
+ *
+ * @return {@link CookieSpec cookie specification}
+ *
+ * @throws IllegalStateException if a policy with the given name cannot be found
+ */
+ public CookieSpec getCookieSpec(final String name)
+ throws IllegalStateException {
+ return getCookieSpec(name, null);
+ }
+
+ /**
+ * Obtains a list containing the names of all registered {@link CookieSpec cookie
+ * specs}.
+ *
+ * Note that the DEFAULT policy (if present) is likely to be the same
+ * as one of the other policies, but does not have to be.
+ *
+ * @return list of registered cookie spec names
+ */
+ public List<String> getSpecNames(){
+ return new ArrayList<String>(registeredSpecs.keySet());
+ }
+
+ /**
+ * Populates the internal collection of registered {@link CookieSpec cookie
+ * specs} with the content of the map passed as a parameter.
+ *
+ * @param map cookie specs
+ */
+ public void setItems(final Map<String, CookieSpecFactory> map) {
+ if (map == null) {
+ return;
+ }
+ registeredSpecs.clear();
+ registeredSpecs.putAll(map);
+ }
+
+ public CookieSpecProvider lookup(final String name) {
+ return new CookieSpecProvider() {
+
+ public CookieSpec create(final HttpContext context) {
+ final HttpRequest request = (HttpRequest) context.getAttribute(
+ ExecutionContext.HTTP_REQUEST);
+ return getCookieSpec(name, request.getParams());
+ }
+
+ };
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/MalformedCookieException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/MalformedCookieException.java
new file mode 100644
index 000000000..dba7b9b25
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/MalformedCookieException.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals that a cookie is in some way invalid or illegal in a given
+ * context
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class MalformedCookieException extends ProtocolException {
+
+ private static final long serialVersionUID = -6695462944287282185L;
+
+ /**
+ * Creates a new MalformedCookieException with a <tt>null</tt> detail message.
+ */
+ public MalformedCookieException() {
+ super();
+ }
+
+ /**
+ * Creates a new MalformedCookieException with a specified message string.
+ *
+ * @param message The exception detail message
+ */
+ public MalformedCookieException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new MalformedCookieException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public MalformedCookieException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SM.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SM.java
new file mode 100644
index 000000000..463da4d25
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SM.java
@@ -0,0 +1,43 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+/**
+ * Constants and static helpers related to the HTTP state management.
+ *
+ *
+ * @since 4.0
+ */
+public interface SM {
+
+ public static final String COOKIE = "Cookie";
+ public static final String COOKIE2 = "Cookie2";
+ public static final String SET_COOKIE = "Set-Cookie";
+ public static final String SET_COOKIE2 = "Set-Cookie2";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie.java
new file mode 100644
index 000000000..5bd5b7121
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie.java
@@ -0,0 +1,109 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+import java.util.Date;
+
+/**
+ * This interface represents a <code>Set-Cookie</code> response header sent by the
+ * origin server to the HTTP agent in order to maintain a conversational state.
+ *
+ * @since 4.0
+ */
+public interface SetCookie extends Cookie {
+
+ void setValue(String value);
+
+ /**
+ * If a user agent (web browser) presents this cookie to a user, the
+ * cookie's purpose will be described using this comment.
+ *
+ * @param comment
+ *
+ * @see #getComment()
+ */
+ void setComment(String comment);
+
+ /**
+ * Sets expiration date.
+ * <p><strong>Note:</strong> the object returned by this method is considered
+ * immutable. Changing it (e.g. using setTime()) could result in undefined
+ * behaviour. Do so at your peril.</p>
+ *
+ * @param expiryDate the {@link Date} after which this cookie is no longer valid.
+ *
+ * @see Cookie#getExpiryDate
+ *
+ */
+ void setExpiryDate (Date expiryDate);
+
+ /**
+ * Sets the domain attribute.
+ *
+ * @param domain The value of the domain attribute
+ *
+ * @see Cookie#getDomain
+ */
+ void setDomain(String domain);
+
+ /**
+ * Sets the path attribute.
+ *
+ * @param path The value of the path attribute
+ *
+ * @see Cookie#getPath
+ *
+ */
+ void setPath(String path);
+
+ /**
+ * Sets the secure attribute of the cookie.
+ * <p>
+ * When <tt>true</tt> the cookie should only be sent
+ * using a secure protocol (https). This should only be set when
+ * the cookie's originating server used a secure protocol to set the
+ * cookie's value.
+ *
+ * @param secure The value of the secure attribute
+ *
+ * @see #isSecure()
+ */
+ void setSecure (boolean secure);
+
+ /**
+ * Sets the version of the cookie specification to which this
+ * cookie conforms.
+ *
+ * @param version the version of the cookie.
+ *
+ * @see Cookie#getVersion
+ */
+ void setVersion(int version);
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie2.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie2.java
new file mode 100644
index 000000000..bc3508059
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/SetCookie2.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie;
+
+/**
+ * This interface represents a <code>Set-Cookie2</code> response header sent by the
+ * origin server to the HTTP agent in order to maintain a conversational state.
+ *
+ * @since 4.0
+ */
+public interface SetCookie2 extends SetCookie {
+
+ /**
+ * If a user agent (web browser) presents this cookie to a user, the
+ * cookie's purpose will be described by the information at this URL.
+ */
+ void setCommentURL(String commentURL);
+
+ /**
+ * Sets the Port attribute. It restricts the ports to which a cookie
+ * may be returned in a Cookie request header.
+ */
+ void setPorts(int[] ports);
+
+ /**
+ * Set the Discard attribute.
+ *
+ * Note: <tt>Discard</tt> attribute overrides <tt>Max-age</tt>.
+ *
+ * @see #isPersistent()
+ */
+ void setDiscard(boolean discard);
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/package-info.java
new file mode 100644
index 000000000..80a831709
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client HTTP state management APIs.
+ */
+package ch.boye.httpclientandroidlib.cookie;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecPNames.java
new file mode 100644
index 000000000..a93a26f16
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecPNames.java
@@ -0,0 +1,65 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie.params;
+
+/**
+ * Parameter names for HTTP cookie management classes.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use constructor parameters of {@link
+ * ch.boye.httpclientandroidlib.cookie.CookieSpecProvider}s.
+ */
+@Deprecated
+public interface CookieSpecPNames {
+
+ /**
+ * Defines valid date patterns to be used for parsing non-standard
+ * <code>expires</code> attribute. Only required for compatibility
+ * with non-compliant servers that still use <code>expires</code>
+ * defined in the Netscape draft instead of the standard
+ * <code>max-age</code> attribute.
+ * <p>
+ * This parameter expects a value of type {@link java.util.Collection}.
+ * The collection elements must be of type {@link String} compatible
+ * with the syntax of {@link java.text.SimpleDateFormat}.
+ * </p>
+ */
+ public static final String DATE_PATTERNS = "http.protocol.cookie-datepatterns";
+
+ /**
+ * Defines whether cookies should be forced into a single
+ * <code>Cookie</code> request header. Otherwise, each cookie is formatted
+ * as a separate <code>Cookie</code> header.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecParamBean.java
new file mode 100644
index 000000000..0e007a54f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/CookieSpecParamBean.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.cookie.params;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate HTTP cookie parameters using Java Beans
+ * conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use constructor parameters of {@link
+ * ch.boye.httpclientandroidlib.cookie.CookieSpecProvider}s.
+ */
+@Deprecated
+@NotThreadSafe
+public class CookieSpecParamBean extends HttpAbstractParamBean {
+
+ public CookieSpecParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ public void setDatePatterns (final Collection <String> patterns) {
+ params.setParameter(CookieSpecPNames.DATE_PATTERNS, patterns);
+ }
+
+ public void setSingleHeader (final boolean singleHeader) {
+ params.setBooleanParameter(CookieSpecPNames.SINGLE_COOKIE_HEADER, singleHeader);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/package-info.java
new file mode 100644
index 000000000..9314e1e63
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/cookie/params/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Deprecated.
+ * @deprecated (4.3).
+ */
+package ch.boye.httpclientandroidlib.cookie.params;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/AbstractHttpEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/AbstractHttpEntity.java
new file mode 100644
index 000000000..9fc32fa29
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/AbstractHttpEntity.java
@@ -0,0 +1,191 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * Abstract base class for entities.
+ * Provides the commonly used attributes for streamed and self-contained
+ * implementations of {@link HttpEntity HttpEntity}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public abstract class AbstractHttpEntity implements HttpEntity {
+
+ /**
+ * Buffer size for output stream processing.
+ *
+ * @since 4.3
+ */
+ protected static final int OUTPUT_BUFFER_SIZE = 4096;
+
+ protected Header contentType;
+ protected Header contentEncoding;
+ protected boolean chunked;
+
+ /**
+ * Protected default constructor.
+ * The contentType, contentEncoding and chunked attributes of the created object are set to
+ * <code>null</code>, <code>null</code> and <code>false</code>, respectively.
+ */
+ protected AbstractHttpEntity() {
+ super();
+ }
+
+
+ /**
+ * Obtains the Content-Type header.
+ * The default implementation returns the value of the
+ * {@link #contentType contentType} attribute.
+ *
+ * @return the Content-Type header, or <code>null</code>
+ */
+ public Header getContentType() {
+ return this.contentType;
+ }
+
+
+ /**
+ * Obtains the Content-Encoding header.
+ * The default implementation returns the value of the
+ * {@link #contentEncoding contentEncoding} attribute.
+ *
+ * @return the Content-Encoding header, or <code>null</code>
+ */
+ public Header getContentEncoding() {
+ return this.contentEncoding;
+ }
+
+ /**
+ * Obtains the 'chunked' flag.
+ * The default implementation returns the value of the
+ * {@link #chunked chunked} attribute.
+ *
+ * @return the 'chunked' flag
+ */
+ public boolean isChunked() {
+ return this.chunked;
+ }
+
+
+ /**
+ * Specifies the Content-Type header.
+ * The default implementation sets the value of the
+ * {@link #contentType contentType} attribute.
+ *
+ * @param contentType the new Content-Encoding header, or
+ * <code>null</code> to unset
+ */
+ public void setContentType(final Header contentType) {
+ this.contentType = contentType;
+ }
+
+ /**
+ * Specifies the Content-Type header, as a string.
+ * The default implementation calls
+ * {@link #setContentType(Header) setContentType(Header)}.
+ *
+ * @param ctString the new Content-Type header, or
+ * <code>null</code> to unset
+ */
+ public void setContentType(final String ctString) {
+ Header h = null;
+ if (ctString != null) {
+ h = new BasicHeader(HTTP.CONTENT_TYPE, ctString);
+ }
+ setContentType(h);
+ }
+
+
+ /**
+ * Specifies the Content-Encoding header.
+ * The default implementation sets the value of the
+ * {@link #contentEncoding contentEncoding} attribute.
+ *
+ * @param contentEncoding the new Content-Encoding header, or
+ * <code>null</code> to unset
+ */
+ public void setContentEncoding(final Header contentEncoding) {
+ this.contentEncoding = contentEncoding;
+ }
+
+ /**
+ * Specifies the Content-Encoding header, as a string.
+ * The default implementation calls
+ * {@link #setContentEncoding(Header) setContentEncoding(Header)}.
+ *
+ * @param ceString the new Content-Encoding header, or
+ * <code>null</code> to unset
+ */
+ public void setContentEncoding(final String ceString) {
+ Header h = null;
+ if (ceString != null) {
+ h = new BasicHeader(HTTP.CONTENT_ENCODING, ceString);
+ }
+ setContentEncoding(h);
+ }
+
+
+ /**
+ * Specifies the 'chunked' flag.
+ * <p>
+ * Note that the chunked setting is a hint only.
+ * If using HTTP/1.0, chunking is never performed.
+ * Otherwise, even if chunked is false, HttpClient must
+ * use chunk coding if the entity content length is
+ * unknown (-1).
+ * <p>
+ * The default implementation sets the value of the
+ * {@link #chunked chunked} attribute.
+ *
+ * @param b the new 'chunked' flag
+ */
+ public void setChunked(final boolean b) {
+ this.chunked = b;
+ }
+
+
+ /**
+ * The default implementation does not consume anything.
+ *
+ * @deprecated (4.1) Either use {@link #getContent()} and call {@link java.io.InputStream#close()} on that;
+ * otherwise call {@link #writeTo(java.io.OutputStream)} which is required to free the resources.
+ */
+ @Deprecated
+ public void consumeContent() throws IOException {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BasicHttpEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BasicHttpEntity.java
new file mode 100644
index 000000000..74a281b2a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BasicHttpEntity.java
@@ -0,0 +1,125 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * A generic streamed, non-repeatable entity that obtains its content
+ * from an {@link InputStream}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicHttpEntity extends AbstractHttpEntity {
+
+ private InputStream content;
+ private long length;
+
+ /**
+ * Creates a new basic entity.
+ * The content is initially missing, the content length
+ * is set to a negative number.
+ */
+ public BasicHttpEntity() {
+ super();
+ this.length = -1;
+ }
+
+ public long getContentLength() {
+ return this.length;
+ }
+
+ /**
+ * Obtains the content, once only.
+ *
+ * @return the content, if this is the first call to this method
+ * since {@link #setContent setContent} has been called
+ *
+ * @throws IllegalStateException
+ * if the content has not been provided
+ */
+ public InputStream getContent() throws IllegalStateException {
+ Asserts.check(this.content != null, "Content has not been provided");
+ return this.content;
+ }
+
+ /**
+ * Tells that this entity is not repeatable.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isRepeatable() {
+ return false;
+ }
+
+ /**
+ * Specifies the length of the content.
+ *
+ * @param len the number of bytes in the content, or
+ * a negative number to indicate an unknown length
+ */
+ public void setContentLength(final long len) {
+ this.length = len;
+ }
+
+ /**
+ * Specifies the content.
+ *
+ * @param instream the stream to return with the next call to
+ * {@link #getContent getContent}
+ */
+ public void setContent(final InputStream instream) {
+ this.content = instream;
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ final InputStream instream = getContent();
+ try {
+ int l;
+ final byte[] tmp = new byte[OUTPUT_BUFFER_SIZE];
+ while ((l = instream.read(tmp)) != -1) {
+ outstream.write(tmp, 0, l);
+ }
+ } finally {
+ instream.close();
+ }
+ }
+
+ public boolean isStreaming() {
+ return this.content != null;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BufferedHttpEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BufferedHttpEntity.java
new file mode 100644
index 000000000..6cb7495d7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/BufferedHttpEntity.java
@@ -0,0 +1,125 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * A wrapping entity that buffers it content if necessary.
+ * The buffered entity is always repeatable.
+ * If the wrapped entity is repeatable itself, calls are passed through.
+ * If the wrapped entity is not repeatable, the content is read into a
+ * buffer once and provided from there as often as required.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BufferedHttpEntity extends HttpEntityWrapper {
+
+ private final byte[] buffer;
+
+ /**
+ * Creates a new buffered entity wrapper.
+ *
+ * @param entity the entity to wrap, not null
+ * @throws IllegalArgumentException if wrapped is null
+ */
+ public BufferedHttpEntity(final HttpEntity entity) throws IOException {
+ super(entity);
+ if (!entity.isRepeatable() || entity.getContentLength() < 0) {
+ this.buffer = EntityUtils.toByteArray(entity);
+ } else {
+ this.buffer = null;
+ }
+ }
+
+ @Override
+ public long getContentLength() {
+ if (this.buffer != null) {
+ return this.buffer.length;
+ } else {
+ return super.getContentLength();
+ }
+ }
+
+ @Override
+ public InputStream getContent() throws IOException {
+ if (this.buffer != null) {
+ return new ByteArrayInputStream(this.buffer);
+ } else {
+ return super.getContent();
+ }
+ }
+
+ /**
+ * Tells that this entity does not have to be chunked.
+ *
+ * @return <code>false</code>
+ */
+ @Override
+ public boolean isChunked() {
+ return (buffer == null) && super.isChunked();
+ }
+
+ /**
+ * Tells that this entity is repeatable.
+ *
+ * @return <code>true</code>
+ */
+ @Override
+ public boolean isRepeatable() {
+ return true;
+ }
+
+
+ @Override
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ if (this.buffer != null) {
+ outstream.write(this.buffer);
+ } else {
+ super.writeTo(outstream);
+ }
+ }
+
+
+ // non-javadoc, see interface HttpEntity
+ @Override
+ public boolean isStreaming() {
+ return (buffer == null) && super.isStreaming();
+ }
+
+} // class BufferedHttpEntity
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ByteArrayEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ByteArrayEntity.java
new file mode 100644
index 000000000..9f0af3ab8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ByteArrayEntity.java
@@ -0,0 +1,131 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A self contained, repeatable entity that obtains its content from a byte array.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class ByteArrayEntity extends AbstractHttpEntity implements Cloneable {
+
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ protected final byte[] content;
+ private final byte[] b;
+ private final int off, len;
+
+ /**
+ * @since 4.2
+ */
+ @SuppressWarnings("deprecation")
+ public ByteArrayEntity(final byte[] b, final ContentType contentType) {
+ super();
+ Args.notNull(b, "Source byte array");
+ this.content = b;
+ this.b = b;
+ this.off = 0;
+ this.len = this.b.length;
+ if (contentType != null) {
+ setContentType(contentType.toString());
+ }
+ }
+
+ /**
+ * @since 4.2
+ */
+ @SuppressWarnings("deprecation")
+ public ByteArrayEntity(final byte[] b, final int off, final int len, final ContentType contentType) {
+ super();
+ Args.notNull(b, "Source byte array");
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException("off: " + off + " len: " + len + " b.length: " + b.length);
+ }
+ this.content = b;
+ this.b = b;
+ this.off = off;
+ this.len = len;
+ if (contentType != null) {
+ setContentType(contentType.toString());
+ }
+ }
+
+ public ByteArrayEntity(final byte[] b) {
+ this(b, null);
+ }
+
+ public ByteArrayEntity(final byte[] b, final int off, final int len) {
+ this(b, off, len, null);
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public long getContentLength() {
+ return this.len;
+ }
+
+ public InputStream getContent() {
+ return new ByteArrayInputStream(this.b, this.off, this.len);
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ outstream.write(this.b, this.off, this.len);
+ outstream.flush();
+ }
+
+
+ /**
+ * Tells that this entity is not streaming.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isStreaming() {
+ return false;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+} // class ByteArrayEntity
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentLengthStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentLengthStrategy.java
new file mode 100644
index 000000000..4dbc1afaf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentLengthStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+
+/**
+ * Represents a strategy to determine length of the enclosed content entity
+ * based on properties of the HTTP message.
+ *
+ * @since 4.0
+ */
+public interface ContentLengthStrategy {
+
+ public static final int IDENTITY = -1;
+ public static final int CHUNKED = -2;
+
+ /**
+ * Returns length of the given message in bytes. The returned value
+ * must be a non-negative number, {@link #IDENTITY} if the end of the
+ * message will be delimited by the end of connection, or {@link #CHUNKED}
+ * if the message is chunk coded
+ *
+ * @param message HTTP message
+ * @return content length, {@link #IDENTITY}, or {@link #CHUNKED}
+ *
+ * @throws HttpException in case of HTTP protocol violation
+ */
+ long determineLength(HttpMessage message) throws HttpException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentProducer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentProducer.java
new file mode 100644
index 000000000..3ced2e48b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentProducer.java
@@ -0,0 +1,44 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An abstract entity content producer.
+ *<p>Content producers are expected to be able to produce their
+ * content multiple times</p>
+ *
+ * @since 4.0
+ */
+public interface ContentProducer {
+
+ void writeTo(OutputStream outstream) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentType.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentType.java
new file mode 100644
index 000000000..e486b83b3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/ContentType.java
@@ -0,0 +1,305 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.Serializable;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.message.BasicHeaderValueFormatter;
+import ch.boye.httpclientandroidlib.message.BasicHeaderValueParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+/**
+ * Content type information consisting of a MIME type and an optional charset.
+ * <p/>
+ * This class makes no attempts to verify validity of the MIME type.
+ * The input parameters of the {@link #create(String, String)} method, however, may not
+ * contain characters <">, <;>, <,> reserved by the HTTP specification.
+ *
+ * @since 4.2
+ */
+@Immutable
+public final class ContentType implements Serializable {
+
+ private static final long serialVersionUID = -7768694718232371896L;
+
+ // constants
+ public static final ContentType APPLICATION_ATOM_XML = create(
+ "application/atom+xml", Consts.ISO_8859_1);
+ public static final ContentType APPLICATION_FORM_URLENCODED = create(
+ "application/x-www-form-urlencoded", Consts.ISO_8859_1);
+ public static final ContentType APPLICATION_JSON = create(
+ "application/json", Consts.UTF_8);
+ public static final ContentType APPLICATION_OCTET_STREAM = create(
+ "application/octet-stream", (Charset) null);
+ public static final ContentType APPLICATION_SVG_XML = create(
+ "application/svg+xml", Consts.ISO_8859_1);
+ public static final ContentType APPLICATION_XHTML_XML = create(
+ "application/xhtml+xml", Consts.ISO_8859_1);
+ public static final ContentType APPLICATION_XML = create(
+ "application/xml", Consts.ISO_8859_1);
+ public static final ContentType MULTIPART_FORM_DATA = create(
+ "multipart/form-data", Consts.ISO_8859_1);
+ public static final ContentType TEXT_HTML = create(
+ "text/html", Consts.ISO_8859_1);
+ public static final ContentType TEXT_PLAIN = create(
+ "text/plain", Consts.ISO_8859_1);
+ public static final ContentType TEXT_XML = create(
+ "text/xml", Consts.ISO_8859_1);
+ public static final ContentType WILDCARD = create(
+ "*/*", (Charset) null);
+
+ // defaults
+ public static final ContentType DEFAULT_TEXT = TEXT_PLAIN;
+ public static final ContentType DEFAULT_BINARY = APPLICATION_OCTET_STREAM;
+
+ private final String mimeType;
+ private final Charset charset;
+ private final NameValuePair[] params;
+
+ ContentType(
+ final String mimeType,
+ final Charset charset) {
+ this.mimeType = mimeType;
+ this.charset = charset;
+ this.params = null;
+ }
+
+ ContentType(
+ final String mimeType,
+ final NameValuePair[] params) throws UnsupportedCharsetException {
+ this.mimeType = mimeType;
+ this.params = params;
+ final String s = getParameter("charset");
+ this.charset = !TextUtils.isBlank(s) ? Charset.forName(s) : null;
+ }
+
+ public String getMimeType() {
+ return this.mimeType;
+ }
+
+ public Charset getCharset() {
+ return this.charset;
+ }
+
+ /**
+ * @since 4.3
+ */
+ public String getParameter(final String name) {
+ Args.notEmpty(name, "Parameter name");
+ if (this.params == null) {
+ return null;
+ }
+ for (final NameValuePair param: this.params) {
+ if (param.getName().equalsIgnoreCase(name)) {
+ return param.getValue();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Generates textual representation of this content type which can be used as the value
+ * of a <code>Content-Type</code> header.
+ */
+ @Override
+ public String toString() {
+ final CharArrayBuffer buf = new CharArrayBuffer(64);
+ buf.append(this.mimeType);
+ if (this.params != null) {
+ buf.append("; ");
+ BasicHeaderValueFormatter.INSTANCE.formatParameters(buf, this.params, false);
+ } else if (this.charset != null) {
+ buf.append("; charset=");
+ buf.append(this.charset.name());
+ }
+ return buf.toString();
+ }
+
+ private static boolean valid(final String s) {
+ for (int i = 0; i < s.length(); i++) {
+ final char ch = s.charAt(i);
+ if (ch == '"' || ch == ',' || ch == ';') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Creates a new instance of {@link ContentType}.
+ *
+ * @param mimeType MIME type. It may not be <code>null</code> or empty. It may not contain
+ * characters <">, <;>, <,> reserved by the HTTP specification.
+ * @param charset charset.
+ * @return content type
+ */
+ public static ContentType create(final String mimeType, final Charset charset) {
+ final String type = Args.notBlank(mimeType, "MIME type").toLowerCase(Locale.US);
+ Args.check(valid(type), "MIME type may not contain reserved characters");
+ return new ContentType(type, charset);
+ }
+
+ /**
+ * Creates a new instance of {@link ContentType} without a charset.
+ *
+ * @param mimeType MIME type. It may not be <code>null</code> or empty. It may not contain
+ * characters <">, <;>, <,> reserved by the HTTP specification.
+ * @return content type
+ */
+ public static ContentType create(final String mimeType) {
+ return new ContentType(mimeType, (Charset) null);
+ }
+
+ /**
+ * Creates a new instance of {@link ContentType}.
+ *
+ * @param mimeType MIME type. It may not be <code>null</code> or empty. It may not contain
+ * characters <">, <;>, <,> reserved by the HTTP specification.
+ * @param charset charset. It may not contain characters <">, <;>, <,> reserved by the HTTP
+ * specification. This parameter is optional.
+ * @return content type
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public static ContentType create(
+ final String mimeType, final String charset) throws UnsupportedCharsetException {
+ return create(mimeType, !TextUtils.isBlank(charset) ? Charset.forName(charset) : null);
+ }
+
+ private static ContentType create(final HeaderElement helem) {
+ final String mimeType = helem.getName();
+ final NameValuePair[] params = helem.getParameters();
+ return new ContentType(mimeType, params != null && params.length > 0 ? params : null);
+ }
+
+ /**
+ * Parses textual representation of <code>Content-Type</code> value.
+ *
+ * @param s text
+ * @return content type
+ * @throws ParseException if the given text does not represent a valid
+ * <code>Content-Type</code> value.
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public static ContentType parse(
+ final String s) throws ParseException, UnsupportedCharsetException {
+ Args.notNull(s, "Content type");
+ final CharArrayBuffer buf = new CharArrayBuffer(s.length());
+ buf.append(s);
+ final ParserCursor cursor = new ParserCursor(0, s.length());
+ final HeaderElement[] elements = BasicHeaderValueParser.INSTANCE.parseElements(buf, cursor);
+ if (elements.length > 0) {
+ return create(elements[0]);
+ } else {
+ throw new ParseException("Invalid content type: " + s);
+ }
+ }
+
+ /**
+ * Extracts <code>Content-Type</code> value from {@link HttpEntity} exactly as
+ * specified by the <code>Content-Type</code> header of the entity. Returns <code>null</code>
+ * if not specified.
+ *
+ * @param entity HTTP entity
+ * @return content type
+ * @throws ParseException if the given text does not represent a valid
+ * <code>Content-Type</code> value.
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public static ContentType get(
+ final HttpEntity entity) throws ParseException, UnsupportedCharsetException {
+ if (entity == null) {
+ return null;
+ }
+ final Header header = entity.getContentType();
+ if (header != null) {
+ final HeaderElement[] elements = header.getElements();
+ if (elements.length > 0) {
+ return create(elements[0]);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Extracts <code>Content-Type</code> value from {@link HttpEntity} or returns the default value
+ * {@link #DEFAULT_TEXT} if not explicitly specified.
+ *
+ * @param entity HTTP entity
+ * @return content type
+ * @throws ParseException if the given text does not represent a valid
+ * <code>Content-Type</code> value.
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public static ContentType getOrDefault(
+ final HttpEntity entity) throws ParseException, UnsupportedCharsetException {
+ final ContentType contentType = get(entity);
+ return contentType != null ? contentType : DEFAULT_TEXT;
+ }
+
+ /**
+ * Creates a new instance with this MIME type and the given Charset.
+ *
+ * @param charset charset
+ * @return a new instance with this MIME type and the given Charset.
+ * @since 4.3
+ */
+ public ContentType withCharset(final Charset charset) {
+ return create(this.getMimeType(), charset);
+ }
+
+ /**
+ * Creates a new instance with this MIME type and the given Charset name.
+ *
+ * @param charset name
+ * @return a new instance with this MIME type and the given Charset name.
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ * @since 4.3
+ */
+ public ContentType withCharset(final String charset) {
+ return create(this.getMimeType(), charset);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/EntityTemplate.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/EntityTemplate.java
new file mode 100644
index 000000000..8e5a79431
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/EntityTemplate.java
@@ -0,0 +1,76 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Entity that delegates the process of content generation
+ * to a {@link ContentProducer}.
+ *
+ * @since 4.0
+ */
+public class EntityTemplate extends AbstractHttpEntity {
+
+ private final ContentProducer contentproducer;
+
+ public EntityTemplate(final ContentProducer contentproducer) {
+ super();
+ this.contentproducer = Args.notNull(contentproducer, "Content producer");
+ }
+
+ public long getContentLength() {
+ return -1;
+ }
+
+ public InputStream getContent() throws IOException {
+ final ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ writeTo(buf);
+ return new ByteArrayInputStream(buf.toByteArray());
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ this.contentproducer.writeTo(outstream);
+ }
+
+ public boolean isStreaming() {
+ return false;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/FileEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/FileEntity.java
new file mode 100644
index 000000000..8801d3733
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/FileEntity.java
@@ -0,0 +1,121 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A self contained, repeatable entity that obtains its content from a file.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class FileEntity extends AbstractHttpEntity implements Cloneable {
+
+ protected final File file;
+
+ /**
+ * @deprecated (4.1.3) {@link #FileEntity(File, ContentType)}
+ */
+ @Deprecated
+ public FileEntity(final File file, final String contentType) {
+ super();
+ this.file = Args.notNull(file, "File");
+ setContentType(contentType);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public FileEntity(final File file, final ContentType contentType) {
+ super();
+ this.file = Args.notNull(file, "File");
+ if (contentType != null) {
+ setContentType(contentType.toString());
+ }
+ }
+
+ /**
+ * @since 4.2
+ */
+ public FileEntity(final File file) {
+ super();
+ this.file = Args.notNull(file, "File");
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public long getContentLength() {
+ return this.file.length();
+ }
+
+ public InputStream getContent() throws IOException {
+ return new FileInputStream(this.file);
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ final InputStream instream = new FileInputStream(this.file);
+ try {
+ final byte[] tmp = new byte[OUTPUT_BUFFER_SIZE];
+ int l;
+ while ((l = instream.read(tmp)) != -1) {
+ outstream.write(tmp, 0, l);
+ }
+ outstream.flush();
+ } finally {
+ instream.close();
+ }
+ }
+
+ /**
+ * Tells that this entity is not streaming.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isStreaming() {
+ return false;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ // File instance is considered immutable
+ // No need to make a copy of it
+ return super.clone();
+ }
+
+} // class FileEntity
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/HttpEntityWrapper.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/HttpEntityWrapper.java
new file mode 100644
index 000000000..77b1245f4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/HttpEntityWrapper.java
@@ -0,0 +1,105 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Base class for wrapping entities.
+ * Keeps a {@link #wrappedEntity wrappedEntity} and delegates all
+ * calls to it. Implementations of wrapping entities can derive
+ * from this class and need to override only those methods that
+ * should not be delegated to the wrapped entity.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpEntityWrapper implements HttpEntity {
+
+ /** The wrapped entity. */
+ protected HttpEntity wrappedEntity;
+
+ /**
+ * Creates a new entity wrapper.
+ */
+ public HttpEntityWrapper(final HttpEntity wrappedEntity) {
+ super();
+ this.wrappedEntity = Args.notNull(wrappedEntity, "Wrapped entity");
+ } // constructor
+
+ public boolean isRepeatable() {
+ return wrappedEntity.isRepeatable();
+ }
+
+ public boolean isChunked() {
+ return wrappedEntity.isChunked();
+ }
+
+ public long getContentLength() {
+ return wrappedEntity.getContentLength();
+ }
+
+ public Header getContentType() {
+ return wrappedEntity.getContentType();
+ }
+
+ public Header getContentEncoding() {
+ return wrappedEntity.getContentEncoding();
+ }
+
+ public InputStream getContent()
+ throws IOException {
+ return wrappedEntity.getContent();
+ }
+
+ public void writeTo(final OutputStream outstream)
+ throws IOException {
+ wrappedEntity.writeTo(outstream);
+ }
+
+ public boolean isStreaming() {
+ return wrappedEntity.isStreaming();
+ }
+
+ /**
+ * @deprecated (4.1) Either use {@link #getContent()} and call {@link java.io.InputStream#close()} on that;
+ * otherwise call {@link #writeTo(OutputStream)} which is required to free the resources.
+ */
+ @Deprecated
+ public void consumeContent() throws IOException {
+ wrappedEntity.consumeContent();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/InputStreamEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/InputStreamEntity.java
new file mode 100644
index 000000000..8a53ef68c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/InputStreamEntity.java
@@ -0,0 +1,155 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A streamed, non-repeatable entity that obtains its content from
+ * an {@link InputStream}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class InputStreamEntity extends AbstractHttpEntity {
+
+ private final InputStream content;
+ private final long length;
+
+ /**
+ * Creates an entity with an unknown length.
+ * Equivalent to {@code new InputStreamEntity(instream, -1)}.
+ *
+ * @param instream input stream
+ * @throws IllegalArgumentException if {@code instream} is {@code null}
+ * @since 4.3
+ */
+ public InputStreamEntity(final InputStream instream) {
+ this(instream, -1);
+ }
+
+ /**
+ * Creates an entity with a specified content length.
+ *
+ * @param instream input stream
+ * @param length of the input stream, {@code -1} if unknown
+ * @throws IllegalArgumentException if {@code instream} is {@code null}
+ */
+ public InputStreamEntity(final InputStream instream, final long length) {
+ this(instream, length, null);
+ }
+
+ /**
+ * Creates an entity with a content type and unknown length.
+ * Equivalent to {@code new InputStreamEntity(instream, -1, contentType)}.
+ *
+ * @param instream input stream
+ * @param contentType content type
+ * @throws IllegalArgumentException if {@code instream} is {@code null}
+ * @since 4.3
+ */
+ public InputStreamEntity(final InputStream instream, final ContentType contentType) {
+ this(instream, -1, contentType);
+ }
+
+ /**
+ * @param instream input stream
+ * @param length of the input stream, {@code -1} if unknown
+ * @param contentType for specifying the {@code Content-Type} header, may be {@code null}
+ * @throws IllegalArgumentException if {@code instream} is {@code null}
+ * @since 4.2
+ */
+ public InputStreamEntity(final InputStream instream, final long length, final ContentType contentType) {
+ super();
+ this.content = Args.notNull(instream, "Source input stream");
+ this.length = length;
+ if (contentType != null) {
+ setContentType(contentType.toString());
+ }
+ }
+
+ public boolean isRepeatable() {
+ return false;
+ }
+
+ /**
+ * @return the content length or {@code -1} if unknown
+ */
+ public long getContentLength() {
+ return this.length;
+ }
+
+ public InputStream getContent() throws IOException {
+ return this.content;
+ }
+
+ /**
+ * Writes bytes from the {@code InputStream} this entity was constructed
+ * with to an {@code OutputStream}. The content length
+ * determines how many bytes are written. If the length is unknown ({@code -1}), the
+ * stream will be completely consumed (to the end of the stream).
+ *
+ */
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ final InputStream instream = this.content;
+ try {
+ final byte[] buffer = new byte[OUTPUT_BUFFER_SIZE];
+ int l;
+ if (this.length < 0) {
+ // consume until EOF
+ while ((l = instream.read(buffer)) != -1) {
+ outstream.write(buffer, 0, l);
+ }
+ } else {
+ // consume no more than length
+ long remaining = this.length;
+ while (remaining > 0) {
+ l = instream.read(buffer, 0, (int)Math.min(OUTPUT_BUFFER_SIZE, remaining));
+ if (l == -1) {
+ break;
+ }
+ outstream.write(buffer, 0, l);
+ remaining -= l;
+ }
+ }
+ } finally {
+ instream.close();
+ }
+ }
+
+ public boolean isStreaming() {
+ return true;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/SerializableEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/SerializableEntity.java
new file mode 100644
index 000000000..f5e125309
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/SerializableEntity.java
@@ -0,0 +1,126 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A streamed entity that obtains its content from a {@link Serializable}.
+ * The content obtained from the {@link Serializable} instance can
+ * optionally be buffered in a byte array in order to make the
+ * entity self-contained and repeatable.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class SerializableEntity extends AbstractHttpEntity {
+
+ private byte[] objSer;
+
+ private Serializable objRef;
+
+ /**
+ * Creates new instance of this class.
+ *
+ * @param ser input
+ * @param bufferize tells whether the content should be
+ * stored in an internal buffer
+ * @throws IOException in case of an I/O error
+ */
+ public SerializableEntity(final Serializable ser, final boolean bufferize) throws IOException {
+ super();
+ Args.notNull(ser, "Source object");
+ if (bufferize) {
+ createBytes(ser);
+ } else {
+ this.objRef = ser;
+ }
+ }
+
+ /**
+ * @since 4.3
+ */
+ public SerializableEntity(final Serializable ser) {
+ super();
+ Args.notNull(ser, "Source object");
+ this.objRef = ser;
+ }
+
+ private void createBytes(final Serializable ser) throws IOException {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final ObjectOutputStream out = new ObjectOutputStream(baos);
+ out.writeObject(ser);
+ out.flush();
+ this.objSer = baos.toByteArray();
+ }
+
+ public InputStream getContent() throws IOException, IllegalStateException {
+ if (this.objSer == null) {
+ createBytes(this.objRef);
+ }
+ return new ByteArrayInputStream(this.objSer);
+ }
+
+ public long getContentLength() {
+ if (this.objSer == null) {
+ return -1;
+ } else {
+ return this.objSer.length;
+ }
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public boolean isStreaming() {
+ return this.objSer == null;
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ if (this.objSer == null) {
+ final ObjectOutputStream out = new ObjectOutputStream(outstream);
+ out.writeObject(this.objRef);
+ out.flush();
+ } else {
+ outstream.write(this.objSer);
+ outstream.flush();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/StringEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/StringEntity.java
new file mode 100644
index 000000000..bf4889119
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/StringEntity.java
@@ -0,0 +1,188 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A self contained, repeatable entity that obtains its content from
+ * a {@link String}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class StringEntity extends AbstractHttpEntity implements Cloneable {
+
+ protected final byte[] content;
+
+ /**
+ * Creates a StringEntity with the specified content and content type.
+ *
+ * @param string content to be used. Not {@code null}.
+ * @param contentType content type to be used. May be {@code null}, in which case the default
+ * MIME type {@link ContentType#TEXT_PLAIN} is assumed.
+ *
+ * @throws IllegalArgumentException if the string parameter is null
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ * @since 4.2
+ */
+ public StringEntity(final String string, final ContentType contentType) throws UnsupportedCharsetException {
+ super();
+ Args.notNull(string, "Source string");
+ Charset charset = contentType != null ? contentType.getCharset() : null;
+ if (charset == null) {
+ charset = HTTP.DEF_CONTENT_CHARSET;
+ }
+ try {
+ this.content = string.getBytes(charset.name());
+ } catch (final UnsupportedEncodingException ex) {
+ // should never happen
+ throw new UnsupportedCharsetException(charset.name());
+ }
+ if (contentType != null) {
+ setContentType(contentType.toString());
+ }
+ }
+
+ /**
+ * Creates a StringEntity with the specified content, MIME type and charset
+ *
+ * @param string content to be used. Not {@code null}.
+ * @param mimeType MIME type to be used. May be {@code null}, in which case the default
+ * is {@link HTTP#PLAIN_TEXT_TYPE} i.e. "text/plain"
+ * @param charset character set to be used. May be {@code null}, in which case the default
+ * is {@link HTTP#DEF_CONTENT_CHARSET} i.e. "ISO-8859-1"
+ * @throws UnsupportedEncodingException If the named charset is not supported.
+ *
+ * @since 4.1
+ * @throws IllegalArgumentException if the string parameter is null
+ *
+ * @deprecated (4.1.3) use {@link #StringEntity(String, ContentType)}
+ */
+ @Deprecated
+ public StringEntity(
+ final String string, final String mimeType, final String charset) throws UnsupportedEncodingException {
+ super();
+ Args.notNull(string, "Source string");
+ final String mt = mimeType != null ? mimeType : HTTP.PLAIN_TEXT_TYPE;
+ final String cs = charset != null ? charset :HTTP.DEFAULT_CONTENT_CHARSET;
+ this.content = string.getBytes(cs);
+ setContentType(mt + HTTP.CHARSET_PARAM + cs);
+ }
+
+ /**
+ * Creates a StringEntity with the specified content and charset. The MIME type defaults
+ * to "text/plain".
+ *
+ * @param string content to be used. Not {@code null}.
+ * @param charset character set to be used. May be {@code null}, in which case the default
+ * is {@link HTTP#DEF_CONTENT_CHARSET} is assumed
+ *
+ * @throws IllegalArgumentException if the string parameter is null
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public StringEntity(final String string, final String charset)
+ throws UnsupportedCharsetException {
+ this(string, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), charset));
+ }
+
+ /**
+ * Creates a StringEntity with the specified content and charset. The MIME type defaults
+ * to "text/plain".
+ *
+ * @param string content to be used. Not {@code null}.
+ * @param charset character set to be used. May be {@code null}, in which case the default
+ * is {@link HTTP#DEF_CONTENT_CHARSET} is assumed
+ *
+ * @throws IllegalArgumentException if the string parameter is null
+ *
+ * @since 4.2
+ */
+ public StringEntity(final String string, final Charset charset) {
+ this(string, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), charset));
+ }
+
+ /**
+ * Creates a StringEntity with the specified content. The content type defaults to
+ * {@link ContentType#TEXT_PLAIN}.
+ *
+ * @param string content to be used. Not {@code null}.
+ *
+ * @throws IllegalArgumentException if the string parameter is null
+ * @throws UnsupportedEncodingException if the default HTTP charset is not supported.
+ */
+ public StringEntity(final String string)
+ throws UnsupportedEncodingException {
+ this(string, ContentType.DEFAULT_TEXT);
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public long getContentLength() {
+ return this.content.length;
+ }
+
+ public InputStream getContent() throws IOException {
+ return new ByteArrayInputStream(this.content);
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ outstream.write(this.content);
+ outstream.flush();
+ }
+
+ /**
+ * Tells that this entity is not streaming.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isStreaming() {
+ return false;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+} // class StringEntity
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/AbstractMultipartForm.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/AbstractMultipartForm.java
new file mode 100644
index 000000000..ade6bfe4b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/AbstractMultipartForm.java
@@ -0,0 +1,211 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.entity.mime.content.ContentBody;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.ByteArrayBuffer;
+
+/**
+ * HttpMultipart represents a collection of MIME multipart encoded content bodies. This class is
+ * capable of operating either in the strict (RFC 822, RFC 2045, RFC 2046 compliant) or
+ * the browser compatible modes.
+ *
+ * @since 4.3
+ */
+abstract class AbstractMultipartForm {
+
+ private static ByteArrayBuffer encode(
+ final Charset charset, final String string) {
+ final ByteBuffer encoded = charset.encode(CharBuffer.wrap(string));
+ final ByteArrayBuffer bab = new ByteArrayBuffer(encoded.remaining());
+ bab.append(encoded.array(), encoded.position(), encoded.remaining());
+ return bab;
+ }
+
+ private static void writeBytes(
+ final ByteArrayBuffer b, final OutputStream out) throws IOException {
+ out.write(b.buffer(), 0, b.length());
+ }
+
+ private static void writeBytes(
+ final String s, final Charset charset, final OutputStream out) throws IOException {
+ final ByteArrayBuffer b = encode(charset, s);
+ writeBytes(b, out);
+ }
+
+ private static void writeBytes(
+ final String s, final OutputStream out) throws IOException {
+ final ByteArrayBuffer b = encode(MIME.DEFAULT_CHARSET, s);
+ writeBytes(b, out);
+ }
+
+ protected static void writeField(
+ final MinimalField field, final OutputStream out) throws IOException {
+ writeBytes(field.getName(), out);
+ writeBytes(FIELD_SEP, out);
+ writeBytes(field.getBody(), out);
+ writeBytes(CR_LF, out);
+ }
+
+ protected static void writeField(
+ final MinimalField field, final Charset charset, final OutputStream out) throws IOException {
+ writeBytes(field.getName(), charset, out);
+ writeBytes(FIELD_SEP, out);
+ writeBytes(field.getBody(), charset, out);
+ writeBytes(CR_LF, out);
+ }
+
+ private static final ByteArrayBuffer FIELD_SEP = encode(MIME.DEFAULT_CHARSET, ": ");
+ private static final ByteArrayBuffer CR_LF = encode(MIME.DEFAULT_CHARSET, "\r\n");
+ private static final ByteArrayBuffer TWO_DASHES = encode(MIME.DEFAULT_CHARSET, "--");
+
+ private final String subType;
+ protected final Charset charset;
+ private final String boundary;
+
+ /**
+ * Creates an instance with the specified settings.
+ *
+ * @param subType MIME subtype - must not be {@code null}
+ * @param charset the character set to use. May be {@code null}, in which case {@link MIME#DEFAULT_CHARSET} - i.e. US-ASCII - is used.
+ * @param boundary to use - must not be {@code null}
+ * @throws IllegalArgumentException if charset is null or boundary is null
+ */
+ public AbstractMultipartForm(final String subType, final Charset charset, final String boundary) {
+ super();
+ Args.notNull(subType, "Multipart subtype");
+ Args.notNull(boundary, "Multipart boundary");
+ this.subType = subType;
+ this.charset = charset != null ? charset : MIME.DEFAULT_CHARSET;
+ this.boundary = boundary;
+ }
+
+ public AbstractMultipartForm(final String subType, final String boundary) {
+ this(subType, null, boundary);
+ }
+
+ public String getSubType() {
+ return this.subType;
+ }
+
+ public Charset getCharset() {
+ return this.charset;
+ }
+
+ public abstract List<FormBodyPart> getBodyParts();
+
+ public String getBoundary() {
+ return this.boundary;
+ }
+
+ void doWriteTo(
+ final OutputStream out,
+ final boolean writeContent) throws IOException {
+
+ final ByteArrayBuffer boundary = encode(this.charset, getBoundary());
+ for (final FormBodyPart part: getBodyParts()) {
+ writeBytes(TWO_DASHES, out);
+ writeBytes(boundary, out);
+ writeBytes(CR_LF, out);
+
+ formatMultipartHeader(part, out);
+
+ writeBytes(CR_LF, out);
+
+ if (writeContent) {
+ part.getBody().writeTo(out);
+ }
+ writeBytes(CR_LF, out);
+ }
+ writeBytes(TWO_DASHES, out);
+ writeBytes(boundary, out);
+ writeBytes(TWO_DASHES, out);
+ writeBytes(CR_LF, out);
+ }
+
+ /**
+ * Write the multipart header fields; depends on the style.
+ */
+ protected abstract void formatMultipartHeader(
+ final FormBodyPart part,
+ final OutputStream out) throws IOException;
+
+ /**
+ * Writes out the content in the multipart/form encoding. This method
+ * produces slightly different formatting depending on its compatibility
+ * mode.
+ */
+ public void writeTo(final OutputStream out) throws IOException {
+ doWriteTo(out, true);
+ }
+
+ /**
+ * Determines the total length of the multipart content (content length of
+ * individual parts plus that of extra elements required to delimit the parts
+ * from one another). If any of the @{link BodyPart}s contained in this object
+ * is of a streaming entity of unknown length the total length is also unknown.
+ * <p/>
+ * This method buffers only a small amount of data in order to determine the
+ * total length of the entire entity. The content of individual parts is not
+ * buffered.
+ *
+ * @return total length of the multipart entity if known, <code>-1</code>
+ * otherwise.
+ */
+ public long getTotalLength() {
+ long contentLen = 0;
+ for (final FormBodyPart part: getBodyParts()) {
+ final ContentBody body = part.getBody();
+ final long len = body.getContentLength();
+ if (len >= 0) {
+ contentLen += len;
+ } else {
+ return -1;
+ }
+ }
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try {
+ doWriteTo(out, false);
+ final byte[] extra = out.toByteArray();
+ return contentLen + extra.length;
+ } catch (final IOException ex) {
+ // Should never happen
+ return -1;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/FormBodyPart.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/FormBodyPart.java
new file mode 100644
index 000000000..a3d2c0954
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/FormBodyPart.java
@@ -0,0 +1,116 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.mime.content.AbstractContentBody;
+import ch.boye.httpclientandroidlib.entity.mime.content.ContentBody;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * FormBodyPart class represents a content body that can be used as a part of multipart encoded
+ * entities. This class automatically populates the header with standard fields based on
+ * the content description of the enclosed body.
+ *
+ * @since 4.0
+ */
+public class FormBodyPart {
+
+ private final String name;
+ private final Header header;
+
+ private final ContentBody body;
+
+ public FormBodyPart(final String name, final ContentBody body) {
+ super();
+ Args.notNull(name, "Name");
+ Args.notNull(body, "Body");
+ this.name = name;
+ this.body = body;
+ this.header = new Header();
+
+ generateContentDisp(body);
+ generateContentType(body);
+ generateTransferEncoding(body);
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public ContentBody getBody() {
+ return this.body;
+ }
+
+ public Header getHeader() {
+ return this.header;
+ }
+
+ public void addField(final String name, final String value) {
+ Args.notNull(name, "Field name");
+ this.header.addField(new MinimalField(name, value));
+ }
+
+ protected void generateContentDisp(final ContentBody body) {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("form-data; name=\"");
+ buffer.append(getName());
+ buffer.append("\"");
+ if (body.getFilename() != null) {
+ buffer.append("; filename=\"");
+ buffer.append(body.getFilename());
+ buffer.append("\"");
+ }
+ addField(MIME.CONTENT_DISPOSITION, buffer.toString());
+ }
+
+ protected void generateContentType(final ContentBody body) {
+ final ContentType contentType;
+ if (body instanceof AbstractContentBody) {
+ contentType = ((AbstractContentBody) body).getContentType();
+ } else {
+ contentType = null;
+ }
+ if (contentType != null) {
+ addField(MIME.CONTENT_TYPE, contentType.toString());
+ } else {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(body.getMimeType()); // MimeType cannot be null
+ if (body.getCharset() != null) { // charset may legitimately be null
+ buffer.append("; charset=");
+ buffer.append(body.getCharset());
+ }
+ addField(MIME.CONTENT_TYPE, buffer.toString());
+ }
+ }
+
+ protected void generateTransferEncoding(final ContentBody body) {
+ addField(MIME.CONTENT_TRANSFER_ENC, body.getTransferEncoding()); // TE cannot be null
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/Header.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/Header.java
new file mode 100644
index 000000000..15d70acc9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/Header.java
@@ -0,0 +1,144 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * The header of an entity (see RFC 2045).
+ */
+public class Header implements Iterable<MinimalField> {
+
+ private final List<MinimalField> fields;
+ private final Map<String, List<MinimalField>> fieldMap;
+
+ public Header() {
+ super();
+ this.fields = new LinkedList<MinimalField>();
+ this.fieldMap = new HashMap<String, List<MinimalField>>();
+ }
+
+ public void addField(final MinimalField field) {
+ if (field == null) {
+ return;
+ }
+ final String key = field.getName().toLowerCase(Locale.ENGLISH);
+ List<MinimalField> values = this.fieldMap.get(key);
+ if (values == null) {
+ values = new LinkedList<MinimalField>();
+ this.fieldMap.put(key, values);
+ }
+ values.add(field);
+ this.fields.add(field);
+ }
+
+ public List<MinimalField> getFields() {
+ return new ArrayList<MinimalField>(this.fields);
+ }
+
+ public MinimalField getField(final String name) {
+ if (name == null) {
+ return null;
+ }
+ final String key = name.toLowerCase(Locale.ENGLISH);
+ final List<MinimalField> list = this.fieldMap.get(key);
+ if (list != null && !list.isEmpty()) {
+ return list.get(0);
+ }
+ return null;
+ }
+
+ public List<MinimalField> getFields(final String name) {
+ if (name == null) {
+ return null;
+ }
+ final String key = name.toLowerCase(Locale.ENGLISH);
+ final List<MinimalField> list = this.fieldMap.get(key);
+ if (list == null || list.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ return new ArrayList<MinimalField>(list);
+ }
+ }
+
+ public int removeFields(final String name) {
+ if (name == null) {
+ return 0;
+ }
+ final String key = name.toLowerCase(Locale.ENGLISH);
+ final List<MinimalField> removed = fieldMap.remove(key);
+ if (removed == null || removed.isEmpty()) {
+ return 0;
+ }
+ this.fields.removeAll(removed);
+ return removed.size();
+ }
+
+ public void setField(final MinimalField field) {
+ if (field == null) {
+ return;
+ }
+ final String key = field.getName().toLowerCase(Locale.ENGLISH);
+ final List<MinimalField> list = fieldMap.get(key);
+ if (list == null || list.isEmpty()) {
+ addField(field);
+ return;
+ }
+ list.clear();
+ list.add(field);
+ int firstOccurrence = -1;
+ int index = 0;
+ for (final Iterator<MinimalField> it = this.fields.iterator(); it.hasNext(); index++) {
+ final MinimalField f = it.next();
+ if (f.getName().equalsIgnoreCase(field.getName())) {
+ it.remove();
+ if (firstOccurrence == -1) {
+ firstOccurrence = index;
+ }
+ }
+ }
+ this.fields.add(firstOccurrence, field);
+ }
+
+ public Iterator<MinimalField> iterator() {
+ return Collections.unmodifiableList(fields).iterator();
+ }
+
+ @Override
+ public String toString() {
+ return this.fields.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpBrowserCompatibleMultipart.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpBrowserCompatibleMultipart.java
new file mode 100644
index 000000000..dfc0a657e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpBrowserCompatibleMultipart.java
@@ -0,0 +1,79 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * HttpBrowserCompatibleMultipart represents a collection of MIME multipart encoded
+ * content bodies. This class is emulates browser compatibility, e.g. IE 5 or earlier.
+ *
+ * @since 4.3
+ */
+class HttpBrowserCompatibleMultipart extends AbstractMultipartForm {
+
+ private final List<FormBodyPart> parts;
+
+ public HttpBrowserCompatibleMultipart(
+ final String subType,
+ final Charset charset,
+ final String boundary,
+ final List<FormBodyPart> parts) {
+ super(subType, charset, boundary);
+ this.parts = parts;
+ }
+
+ @Override
+ public List<FormBodyPart> getBodyParts() {
+ return this.parts;
+ }
+
+ /**
+ * Write the multipart header fields; depends on the style.
+ */
+ @Override
+ protected void formatMultipartHeader(
+ final FormBodyPart part,
+ final OutputStream out) throws IOException {
+ // For browser-compatible, only write Content-Disposition
+ // Use content charset
+ final Header header = part.getHeader();
+ final MinimalField cd = header.getField(MIME.CONTENT_DISPOSITION);
+ writeField(cd, this.charset, out);
+ final String filename = part.getBody().getFilename();
+ if (filename != null) {
+ final MinimalField ct = header.getField(MIME.CONTENT_TYPE);
+ writeField(ct, this.charset, out);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpMultipartMode.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpMultipartMode.java
new file mode 100644
index 000000000..ab73e4983
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpMultipartMode.java
@@ -0,0 +1,43 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+/**
+ *
+ * @since 4.0
+ */
+public enum HttpMultipartMode {
+
+ /** RFC 822, RFC 2045, RFC 2046 compliant */
+ STRICT,
+ /** browser-compatible mode, i.e. only write Content-Disposition; use content charset */
+ BROWSER_COMPATIBLE,
+ /** RFC 6532 compliant */
+ RFC6532
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpRFC6532Multipart.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpRFC6532Multipart.java
new file mode 100644
index 000000000..634a12b23
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpRFC6532Multipart.java
@@ -0,0 +1,72 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * HttpRFC6532Multipart represents a collection of MIME multipart encoded content bodies,
+ * implementing the strict (RFC 822, RFC 2045, RFC 2046 compliant) interpretation
+ * of the spec, with the exception of allowing UTF-8 headers, as per RFC6532.
+ *
+ * @since 4.3
+ */
+class HttpRFC6532Multipart extends AbstractMultipartForm {
+
+ private final List<FormBodyPart> parts;
+
+ public HttpRFC6532Multipart(
+ final String subType,
+ final Charset charset,
+ final String boundary,
+ final List<FormBodyPart> parts) {
+ super(subType, charset, boundary);
+ this.parts = parts;
+ }
+
+ @Override
+ public List<FormBodyPart> getBodyParts() {
+ return this.parts;
+ }
+
+ @Override
+ protected void formatMultipartHeader(
+ final FormBodyPart part,
+ final OutputStream out) throws IOException {
+
+ // For RFC6532, we output all fields with UTF-8 encoding.
+ final Header header = part.getHeader();
+ for (final MinimalField field: header) {
+ writeField(field, MIME.UTF8_CHARSET, out);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpStrictMultipart.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpStrictMultipart.java
new file mode 100644
index 000000000..d6e68c6e2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/HttpStrictMultipart.java
@@ -0,0 +1,72 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * HttpStrictMultipart represents a collection of MIME multipart encoded content bodies,
+ * implementing the strict (RFC 822, RFC 2045, RFC 2046 compliant) interpretation
+ * of the spec.
+ *
+ * @since 4.3
+ */
+class HttpStrictMultipart extends AbstractMultipartForm {
+
+ private final List<FormBodyPart> parts;
+
+ public HttpStrictMultipart(
+ final String subType,
+ final Charset charset,
+ final String boundary,
+ final List<FormBodyPart> parts) {
+ super(subType, charset, boundary);
+ this.parts = parts;
+ }
+
+ @Override
+ public List<FormBodyPart> getBodyParts() {
+ return this.parts;
+ }
+
+ @Override
+ protected void formatMultipartHeader(
+ final FormBodyPart part,
+ final OutputStream out) throws IOException {
+
+ // For strict, we output all fields with MIME-standard encoding.
+ final Header header = part.getHeader();
+ for (final MinimalField field: header) {
+ writeField(field, out);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MIME.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MIME.java
new file mode 100644
index 000000000..d5896312d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MIME.java
@@ -0,0 +1,53 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import ch.boye.httpclientandroidlib.Consts;
+
+import java.nio.charset.Charset;
+
+/**
+ *
+ * @since 4.0
+ */
+public final class MIME {
+
+ public static final String CONTENT_TYPE = "Content-Type";
+ public static final String CONTENT_TRANSFER_ENC = "Content-Transfer-Encoding";
+ public static final String CONTENT_DISPOSITION = "Content-Disposition";
+
+ public static final String ENC_8BIT = "8bit";
+ public static final String ENC_BINARY = "binary";
+
+ /** The default character set to be used, i.e. "US-ASCII" */
+ public static final Charset DEFAULT_CHARSET = Consts.ASCII;
+
+ /** UTF-8 is used for RFC6532 */
+ public static final Charset UTF8_CHARSET = Consts.UTF_8;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MinimalField.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MinimalField.java
new file mode 100644
index 000000000..35af51233
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MinimalField.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+/**
+ * Minimal MIME field.
+ *
+ * @since 4.0
+ */
+public class MinimalField {
+
+ private final String name;
+ private final String value;
+
+ public MinimalField(final String name, final String value) {
+ super();
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getBody() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(this.name);
+ buffer.append(": ");
+ buffer.append(this.value);
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartEntityBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartEntityBuilder.java
new file mode 100644
index 000000000..5074001d7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartEntityBuilder.java
@@ -0,0 +1,207 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.mime.content.ByteArrayBody;
+import ch.boye.httpclientandroidlib.entity.mime.content.ContentBody;
+import ch.boye.httpclientandroidlib.entity.mime.content.FileBody;
+import ch.boye.httpclientandroidlib.entity.mime.content.InputStreamBody;
+import ch.boye.httpclientandroidlib.entity.mime.content.StringBody;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Builder for multipart {@link HttpEntity}s.
+ *
+ * @since 4.3
+ */
+public class MultipartEntityBuilder {
+
+ /**
+ * The pool of ASCII chars to be used for generating a multipart boundary.
+ */
+ private final static char[] MULTIPART_CHARS =
+ "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ .toCharArray();
+
+ private final static String DEFAULT_SUBTYPE = "form-data";
+
+ private String subType = DEFAULT_SUBTYPE;
+ private HttpMultipartMode mode = HttpMultipartMode.STRICT;
+ private String boundary = null;
+ private Charset charset = null;
+ private List<FormBodyPart> bodyParts = null;
+
+ public static MultipartEntityBuilder create() {
+ return new MultipartEntityBuilder();
+ }
+
+ MultipartEntityBuilder() {
+ super();
+ }
+
+ public MultipartEntityBuilder setMode(final HttpMultipartMode mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ public MultipartEntityBuilder setLaxMode() {
+ this.mode = HttpMultipartMode.BROWSER_COMPATIBLE;
+ return this;
+ }
+
+ public MultipartEntityBuilder setStrictMode() {
+ this.mode = HttpMultipartMode.STRICT;
+ return this;
+ }
+
+ public MultipartEntityBuilder setBoundary(final String boundary) {
+ this.boundary = boundary;
+ return this;
+ }
+
+ public MultipartEntityBuilder setCharset(final Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ MultipartEntityBuilder addPart(final FormBodyPart bodyPart) {
+ if (bodyPart == null) {
+ return this;
+ }
+ if (this.bodyParts == null) {
+ this.bodyParts = new ArrayList<FormBodyPart>();
+ }
+ this.bodyParts.add(bodyPart);
+ return this;
+ }
+
+ public MultipartEntityBuilder addPart(final String name, final ContentBody contentBody) {
+ Args.notNull(name, "Name");
+ Args.notNull(contentBody, "Content body");
+ return addPart(new FormBodyPart(name, contentBody));
+ }
+
+ public MultipartEntityBuilder addTextBody(
+ final String name, final String text, final ContentType contentType) {
+ return addPart(name, new StringBody(text, contentType));
+ }
+
+ public MultipartEntityBuilder addTextBody(
+ final String name, final String text) {
+ return addTextBody(name, text, ContentType.DEFAULT_TEXT);
+ }
+
+ public MultipartEntityBuilder addBinaryBody(
+ final String name, final byte[] b, final ContentType contentType, final String filename) {
+ return addPart(name, new ByteArrayBody(b, contentType, filename));
+ }
+
+ public MultipartEntityBuilder addBinaryBody(
+ final String name, final byte[] b) {
+ return addBinaryBody(name, b, ContentType.DEFAULT_BINARY, null);
+ }
+
+ public MultipartEntityBuilder addBinaryBody(
+ final String name, final File file, final ContentType contentType, final String filename) {
+ return addPart(name, new FileBody(file, contentType, filename));
+ }
+
+ public MultipartEntityBuilder addBinaryBody(
+ final String name, final File file) {
+ return addBinaryBody(name, file, ContentType.DEFAULT_BINARY, file != null ? file.getName() : null);
+ }
+
+ public MultipartEntityBuilder addBinaryBody(
+ final String name, final InputStream stream, final ContentType contentType,
+ final String filename) {
+ return addPart(name, new InputStreamBody(stream, contentType, filename));
+ }
+
+ public MultipartEntityBuilder addBinaryBody(final String name, final InputStream stream) {
+ return addBinaryBody(name, stream, ContentType.DEFAULT_BINARY, null);
+ }
+
+ private String generateContentType(
+ final String boundary,
+ final Charset charset) {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("multipart/form-data; boundary=");
+ buffer.append(boundary);
+ if (charset != null) {
+ buffer.append("; charset=");
+ buffer.append(charset.name());
+ }
+ return buffer.toString();
+ }
+
+ private String generateBoundary() {
+ final StringBuilder buffer = new StringBuilder();
+ final Random rand = new Random();
+ final int count = rand.nextInt(11) + 30; // a random size from 30 to 40
+ for (int i = 0; i < count; i++) {
+ buffer.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);
+ }
+ return buffer.toString();
+ }
+
+ MultipartFormEntity buildEntity() {
+ final String st = subType != null ? subType : DEFAULT_SUBTYPE;
+ final Charset cs = charset;
+ final String b = boundary != null ? boundary : generateBoundary();
+ final List<FormBodyPart> bps = bodyParts != null ? new ArrayList<FormBodyPart>(bodyParts) :
+ Collections.<FormBodyPart>emptyList();
+ final HttpMultipartMode m = mode != null ? mode : HttpMultipartMode.STRICT;
+ final AbstractMultipartForm form;
+ switch (m) {
+ case BROWSER_COMPATIBLE:
+ form = new HttpBrowserCompatibleMultipart(st, cs, b, bps);
+ break;
+ case RFC6532:
+ form = new HttpRFC6532Multipart(st, cs, b, bps);
+ break;
+ default:
+ form = new HttpStrictMultipart(st, cs, b, bps);
+ }
+ return new MultipartFormEntity(form, generateContentType(b, cs), form.getTotalLength());
+ }
+
+ public HttpEntity build() {
+ return buildEntity();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartFormEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartFormEntity.java
new file mode 100644
index 000000000..9da2f4724
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/MultipartFormEntity.java
@@ -0,0 +1,100 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+class MultipartFormEntity implements HttpEntity {
+
+ private final AbstractMultipartForm multipart;
+ private final Header contentType;
+ private final long contentLength;
+
+ MultipartFormEntity(
+ final AbstractMultipartForm multipart,
+ final String contentType,
+ final long contentLength) {
+ super();
+ this.multipart = multipart;
+ this.contentType = new BasicHeader(HTTP.CONTENT_TYPE, contentType);
+ this.contentLength = contentLength;
+ }
+
+ AbstractMultipartForm getMultipart() {
+ return this.multipart;
+ }
+
+ public boolean isRepeatable() {
+ return this.contentLength != -1;
+ }
+
+ public boolean isChunked() {
+ return !isRepeatable();
+ }
+
+ public boolean isStreaming() {
+ return !isRepeatable();
+ }
+
+ public long getContentLength() {
+ return this.contentLength;
+ }
+
+ public Header getContentType() {
+ return this.contentType;
+ }
+
+ public Header getContentEncoding() {
+ return null;
+ }
+
+ public void consumeContent()
+ throws IOException, UnsupportedOperationException{
+ if (isStreaming()) {
+ throw new UnsupportedOperationException(
+ "Streaming entity does not implement #consumeContent()");
+ }
+ }
+
+ public InputStream getContent() throws IOException {
+ throw new UnsupportedOperationException(
+ "Multipart form entity does not implement #getContent()");
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ this.multipart.writeTo(outstream);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/AbstractContentBody.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/AbstractContentBody.java
new file mode 100644
index 000000000..b6b58ad35
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/AbstractContentBody.java
@@ -0,0 +1,96 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime.content;
+
+import java.nio.charset.Charset;
+
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+public abstract class AbstractContentBody implements ContentBody {
+
+ private final ContentType contentType;
+
+ /**
+ * @since 4.3
+ */
+ public AbstractContentBody(final ContentType contentType) {
+ super();
+ Args.notNull(contentType, "Content type");
+ this.contentType = contentType;
+ }
+
+ /**
+ * @deprecated (4.3) use {@link AbstractContentBody#AbstractContentBody(ContentType)}
+ */
+ @Deprecated
+ public AbstractContentBody(final String mimeType) {
+ this(ContentType.parse(mimeType));
+ }
+
+ /**
+ * @since 4.3
+ */
+ public ContentType getContentType() {
+ return this.contentType;
+ }
+
+ public String getMimeType() {
+ return this.contentType.getMimeType();
+ }
+
+ public String getMediaType() {
+ final String mimeType = this.contentType.getMimeType();
+ final int i = mimeType.indexOf('/');
+ if (i != -1) {
+ return mimeType.substring(0, i);
+ } else {
+ return mimeType;
+ }
+ }
+
+ public String getSubType() {
+ final String mimeType = this.contentType.getMimeType();
+ final int i = mimeType.indexOf('/');
+ if (i != -1) {
+ return mimeType.substring(i + 1);
+ } else {
+ return null;
+ }
+ }
+
+ public String getCharset() {
+ final Charset charset = this.contentType.getCharset();
+ return charset != null ? charset.name() : null;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ByteArrayBody.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ByteArrayBody.java
new file mode 100644
index 000000000..ea60fa047
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ByteArrayBody.java
@@ -0,0 +1,111 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.entity.mime.content;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.mime.MIME;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Binary body part backed by a byte array.
+ *
+ * @see ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder
+ *
+ * @since 4.1
+ */
+public class ByteArrayBody extends AbstractContentBody {
+
+ /**
+ * The contents of the file contained in this part.
+ */
+ private final byte[] data;
+
+ /**
+ * The name of the file contained in this part.
+ */
+ private final String filename;
+
+ /**
+ * Creates a new ByteArrayBody.
+ *
+ * @param data The contents of the file contained in this part.
+ * @param mimeType The MIME type of the file contained in this part.
+ * @param filename The name of the file contained in this part.
+ *
+ * @deprecated (4.3) use {@link ByteArrayBody#ByteArrayBody(byte[], ContentType, String)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public ByteArrayBody(final byte[] data, final String mimeType, final String filename) {
+ this(data, ContentType.create(mimeType), filename);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public ByteArrayBody(final byte[] data, final ContentType contentType, final String filename) {
+ super(contentType);
+ Args.notNull(data, "byte[]");
+ this.data = data;
+ this.filename = filename;
+ }
+
+ /**
+ * Creates a new ByteArrayBody.
+ *
+ * @param data The contents of the file contained in this part.
+ * @param filename The name of the file contained in this part.
+ */
+ public ByteArrayBody(final byte[] data, final String filename) {
+ this(data, "application/octet-stream", filename);
+ }
+
+ public String getFilename() {
+ return filename;
+ }
+
+ public void writeTo(final OutputStream out) throws IOException {
+ out.write(data);
+ }
+
+ @Override
+ public String getCharset() {
+ return null;
+ }
+
+ public String getTransferEncoding() {
+ return MIME.ENC_BINARY;
+ }
+
+ public long getContentLength() {
+ return data.length;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentBody.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentBody.java
new file mode 100644
index 000000000..d62aaff54
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentBody.java
@@ -0,0 +1,43 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime.content;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ *
+ * @since 4.0
+ */
+public interface ContentBody extends ContentDescriptor {
+
+ String getFilename();
+
+ void writeTo(OutputStream out) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentDescriptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentDescriptor.java
new file mode 100644
index 000000000..87237ec23
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/ContentDescriptor.java
@@ -0,0 +1,89 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime.content;
+
+/**
+ * Represents common content properties.
+ */
+public interface ContentDescriptor {
+
+ /**
+ * Returns the body descriptors MIME type.
+ * @see #getMediaType()
+ * @see #getSubType()
+ * @return The MIME type, which has been parsed from the
+ * content-type definition. Must not be null, but
+ * "text/plain", if no content-type was specified.
+ */
+ String getMimeType();
+
+ /**
+ * Gets the defaulted MIME media type for this content.
+ * For example <code>TEXT</code>, <code>IMAGE</code>, <code>MULTIPART</code>
+ * @see #getMimeType()
+ * @return the MIME media type when content-type specified,
+ * otherwise the correct default (<code>TEXT</code>)
+ */
+ String getMediaType();
+
+ /**
+ * Gets the defaulted MIME sub type for this content.
+ * @see #getMimeType()
+ * @return the MIME media type when content-type is specified,
+ * otherwise the correct default (<code>PLAIN</code>)
+ */
+ String getSubType();
+
+ /**
+ * <p>The body descriptors character set, defaulted appropriately for the MIME type.</p>
+ * <p>
+ * For <code>TEXT</code> types, this will be defaulted to <code>us-ascii</code>.
+ * For other types, when the charset parameter is missing this property will be null.
+ * </p>
+ * @return Character set, which has been parsed from the
+ * content-type definition. Not null for <code>TEXT</code> types, when unset will
+ * be set to default <code>us-ascii</code>. For other types, when unset,
+ * null will be returned.
+ */
+ String getCharset();
+
+ /**
+ * Returns the body descriptors transfer encoding.
+ * @return The transfer encoding. Must not be null, but "7bit",
+ * if no transfer-encoding was specified.
+ */
+ String getTransferEncoding();
+
+ /**
+ * Returns the body descriptors content-length.
+ * @return Content length, if known, or -1, to indicate the absence of a
+ * content-length header.
+ */
+ long getContentLength();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/FileBody.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/FileBody.java
new file mode 100644
index 000000000..7641236a4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/FileBody.java
@@ -0,0 +1,144 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime.content;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.mime.MIME;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Binary body part backed by a file.
+ *
+ * @see ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder
+ *
+ * @since 4.0
+ */
+public class FileBody extends AbstractContentBody {
+
+ private final File file;
+ private final String filename;
+
+ /**
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link FileBody#FileBody(File, ContentType, String)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public FileBody(final File file,
+ final String filename,
+ final String mimeType,
+ final String charset) {
+ this(file, ContentType.create(mimeType, charset), filename);
+ }
+
+ /**
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link FileBody#FileBody(File, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public FileBody(final File file,
+ final String mimeType,
+ final String charset) {
+ this(file, null, mimeType, charset);
+ }
+
+ /**
+ * @deprecated (4.3) use {@link FileBody#FileBody(File, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public FileBody(final File file, final String mimeType) {
+ this(file, ContentType.create(mimeType), null);
+ }
+
+ public FileBody(final File file) {
+ this(file, ContentType.DEFAULT_BINARY, file != null ? file.getName() : null);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public FileBody(final File file, final ContentType contentType, final String filename) {
+ super(contentType);
+ Args.notNull(file, "File");
+ this.file = file;
+ this.filename = filename;
+ }
+
+ /**
+ * @since 4.3
+ */
+ public FileBody(final File file, final ContentType contentType) {
+ this(file, contentType, null);
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(this.file);
+ }
+
+ public void writeTo(final OutputStream out) throws IOException {
+ Args.notNull(out, "Output stream");
+ final InputStream in = new FileInputStream(this.file);
+ try {
+ final byte[] tmp = new byte[4096];
+ int l;
+ while ((l = in.read(tmp)) != -1) {
+ out.write(tmp, 0, l);
+ }
+ out.flush();
+ } finally {
+ in.close();
+ }
+ }
+
+ public String getTransferEncoding() {
+ return MIME.ENC_BINARY;
+ }
+
+ public long getContentLength() {
+ return this.file.length();
+ }
+
+ public String getFilename() {
+ return filename;
+ }
+
+ public File getFile() {
+ return this.file;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/InputStreamBody.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/InputStreamBody.java
new file mode 100644
index 000000000..267a78ea5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/InputStreamBody.java
@@ -0,0 +1,112 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime.content;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.mime.MIME;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Binary body part backed by an input stream.
+ *
+ * @see ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder
+ *
+ * @since 4.0
+ */
+public class InputStreamBody extends AbstractContentBody {
+
+ private final InputStream in;
+ private final String filename;
+
+ /**
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link InputStreamBody#InputStreamBody(InputStream, ContentType,
+ * String)} or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public InputStreamBody(final InputStream in, final String mimeType, final String filename) {
+ this(in, ContentType.create(mimeType), filename);
+ }
+
+ public InputStreamBody(final InputStream in, final String filename) {
+ this(in, ContentType.DEFAULT_BINARY, filename);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public InputStreamBody(final InputStream in, final ContentType contentType, final String filename) {
+ super(contentType);
+ Args.notNull(in, "Input stream");
+ this.in = in;
+ this.filename = filename;
+ }
+
+ /**
+ * @since 4.3
+ */
+ public InputStreamBody(final InputStream in, final ContentType contentType) {
+ this(in, contentType, null);
+ }
+
+ public InputStream getInputStream() {
+ return this.in;
+ }
+
+ public void writeTo(final OutputStream out) throws IOException {
+ Args.notNull(out, "Output stream");
+ try {
+ final byte[] tmp = new byte[4096];
+ int l;
+ while ((l = this.in.read(tmp)) != -1) {
+ out.write(tmp, 0, l);
+ }
+ out.flush();
+ } finally {
+ this.in.close();
+ }
+ }
+
+ public String getTransferEncoding() {
+ return MIME.ENC_BINARY;
+ }
+
+ public long getContentLength() {
+ return -1;
+ }
+
+ public String getFilename() {
+ return this.filename;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/StringBody.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/StringBody.java
new file mode 100644
index 000000000..c5ad5632d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/StringBody.java
@@ -0,0 +1,197 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.entity.mime.content;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.entity.mime.MIME;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Text body part backed by a byte array.
+ *
+ * @see ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder
+ *
+ * @since 4.0
+ */
+public class StringBody extends AbstractContentBody {
+
+ private final byte[] content;
+
+ /**
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link StringBody#StringBody(String, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public static StringBody create(
+ final String text,
+ final String mimeType,
+ final Charset charset) throws IllegalArgumentException {
+ try {
+ return new StringBody(text, mimeType, charset);
+ } catch (final UnsupportedEncodingException ex) {
+ throw new IllegalArgumentException("Charset " + charset + " is not supported", ex);
+ }
+ }
+
+ /**
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link StringBody#StringBody(String, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public static StringBody create(
+ final String text, final Charset charset) throws IllegalArgumentException {
+ return create(text, null, charset);
+ }
+
+ /**
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link StringBody#StringBody(String, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public static StringBody create(final String text) throws IllegalArgumentException {
+ return create(text, null, null);
+ }
+
+ /**
+ * Create a StringBody from the specified text, MIME type and character set.
+ *
+ * @param text to be used for the body, not {@code null}
+ * @param mimeType the MIME type, not {@code null}
+ * @param charset the character set, may be {@code null}, in which case the US-ASCII charset is used
+ * @throws UnsupportedEncodingException
+ * @throws IllegalArgumentException if the {@code text} parameter is null
+ *
+ * @deprecated (4.3) use {@link StringBody#StringBody(String, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public StringBody(
+ final String text,
+ final String mimeType,
+ final Charset charset) throws UnsupportedEncodingException {
+ this(text, ContentType.create(mimeType, charset));
+ }
+
+ /**
+ * Create a StringBody from the specified text and character set.
+ * The MIME type is set to "text/plain".
+ *
+ * @param text to be used for the body, not {@code null}
+ * @param charset the character set, may be {@code null}, in which case the US-ASCII charset is used
+ * @throws UnsupportedEncodingException
+ * @throws IllegalArgumentException if the {@code text} parameter is null
+ *
+ * @deprecated (4.3) use {@link StringBody#StringBody(String, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public StringBody(final String text, final Charset charset) throws UnsupportedEncodingException {
+ this(text, "text/plain", charset);
+ }
+
+ /**
+ * Create a StringBody from the specified text.
+ * The MIME type is set to "text/plain".
+ * The {@linkplain Consts#ASCII ASCII} charset is used.
+ *
+ * @param text to be used for the body, not {@code null}
+ * @throws UnsupportedEncodingException
+ * @throws IllegalArgumentException if the {@code text} parameter is null
+ *
+ * @deprecated (4.3) use {@link StringBody#StringBody(String, ContentType)}
+ * or {@link ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder}
+ */
+ @Deprecated
+ public StringBody(final String text) throws UnsupportedEncodingException {
+ this(text, "text/plain", Consts.ASCII);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public StringBody(final String text, final ContentType contentType) {
+ super(contentType);
+ Args.notNull(text, "Text");
+ final Charset charset = contentType.getCharset();
+ final String csname = charset != null ? charset.name() : Consts.ASCII.name();
+ try {
+ this.content = text.getBytes(csname);
+ } catch (final UnsupportedEncodingException ex) {
+ // Should never happen
+ throw new UnsupportedCharsetException(csname);
+ }
+ }
+
+ public Reader getReader() {
+ final Charset charset = getContentType().getCharset();
+ return new InputStreamReader(
+ new ByteArrayInputStream(this.content),
+ charset != null ? charset : Consts.ASCII);
+ }
+
+ public void writeTo(final OutputStream out) throws IOException {
+ Args.notNull(out, "Output stream");
+ final InputStream in = new ByteArrayInputStream(this.content);
+ final byte[] tmp = new byte[4096];
+ int l;
+ while ((l = in.read(tmp)) != -1) {
+ out.write(tmp, 0, l);
+ }
+ out.flush();
+ }
+
+ public String getTransferEncoding() {
+ return MIME.ENC_8BIT;
+ }
+
+ public long getContentLength() {
+ return this.content.length;
+ }
+
+ public String getFilename() {
+ return null;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/package-info.java
new file mode 100644
index 000000000..ff5e2ed0d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/content/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * MIME body part implementations.
+ */
+package ch.boye.httpclientandroidlib.entity.mime.content;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/package-info.java
new file mode 100644
index 000000000..0ef01f9ed
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/mime/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * MIME coded HTTP entity implementations.
+ */
+package ch.boye.httpclientandroidlib.entity.mime;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/package-info.java
new file mode 100644
index 000000000..0027ae98d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/entity/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Core HTTP entity implementations.
+ */
+package ch.boye.httpclientandroidlib.entity;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpClientConnection.java
new file mode 100644
index 000000000..3f3c5f406
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpClientConnection.java
@@ -0,0 +1,323 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.impl.entity.EntityDeserializer;
+import ch.boye.httpclientandroidlib.impl.entity.EntitySerializer;
+import ch.boye.httpclientandroidlib.impl.entity.LaxContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.entity.StrictContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.io.DefaultHttpResponseParser;
+import ch.boye.httpclientandroidlib.impl.io.HttpRequestWriter;
+import ch.boye.httpclientandroidlib.io.EofSensor;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriter;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Abstract client-side HTTP connection capable of transmitting and receiving
+ * data using arbitrary {@link SessionInputBuffer} and
+ * {@link SessionOutputBuffer} implementations.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultBHttpClientConnection}
+ */
+@NotThreadSafe
+@Deprecated
+public abstract class AbstractHttpClientConnection implements HttpClientConnection {
+
+ private final EntitySerializer entityserializer;
+ private final EntityDeserializer entitydeserializer;
+
+ private SessionInputBuffer inbuffer = null;
+ private SessionOutputBuffer outbuffer = null;
+ private EofSensor eofSensor = null;
+ private HttpMessageParser<HttpResponse> responseParser = null;
+ private HttpMessageWriter<HttpRequest> requestWriter = null;
+ private HttpConnectionMetricsImpl metrics = null;
+
+ /**
+ * Creates an instance of this class.
+ * <p>
+ * This constructor will invoke {@link #createEntityDeserializer()}
+ * and {@link #createEntitySerializer()} methods in order to initialize
+ * HTTP entity serializer and deserializer implementations for this
+ * connection.
+ */
+ public AbstractHttpClientConnection() {
+ super();
+ this.entityserializer = createEntitySerializer();
+ this.entitydeserializer = createEntityDeserializer();
+ }
+
+ /**
+ * Asserts if the connection is open.
+ *
+ * @throws IllegalStateException if the connection is not open.
+ */
+ protected abstract void assertOpen() throws IllegalStateException;
+
+ /**
+ * Creates an instance of {@link EntityDeserializer} with the
+ * {@link LaxContentLengthStrategy} implementation to be used for
+ * de-serializing entities received over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to create
+ * instances of {@link EntityDeserializer} using a custom
+ * {@link ch.boye.httpclientandroidlib.entity.ContentLengthStrategy}.
+ *
+ * @return HTTP entity deserializer
+ */
+ protected EntityDeserializer createEntityDeserializer() {
+ return new EntityDeserializer(new LaxContentLengthStrategy());
+ }
+
+ /**
+ * Creates an instance of {@link EntitySerializer} with the
+ * {@link StrictContentLengthStrategy} implementation to be used for
+ * serializing HTTP entities sent over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to create
+ * instances of {@link EntitySerializer} using a custom
+ * {@link ch.boye.httpclientandroidlib.entity.ContentLengthStrategy}.
+ *
+ * @return HTTP entity serialzier.
+ */
+ protected EntitySerializer createEntitySerializer() {
+ return new EntitySerializer(new StrictContentLengthStrategy());
+ }
+
+ /**
+ * Creates an instance of {@link DefaultHttpResponseFactory} to be used
+ * for creating {@link HttpResponse} objects received by over this
+ * connection.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a different implementation of the {@link HttpResponseFactory} interface.
+ *
+ * @return HTTP response factory.
+ */
+ protected HttpResponseFactory createHttpResponseFactory() {
+ return DefaultHttpResponseFactory.INSTANCE;
+ }
+
+ /**
+ * Creates an instance of {@link HttpMessageParser} to be used for parsing
+ * HTTP responses received over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a different implementation of the {@link HttpMessageParser} interface or
+ * to pass a different implementation of the
+ * {@link ch.boye.httpclientandroidlib.message.LineParser} to the the
+ * {@link DefaultHttpResponseParser} constructor.
+ *
+ * @param buffer the session input buffer.
+ * @param responseFactory the HTTP response factory.
+ * @param params HTTP parameters.
+ * @return HTTP message parser.
+ */
+ protected HttpMessageParser<HttpResponse> createResponseParser(
+ final SessionInputBuffer buffer,
+ final HttpResponseFactory responseFactory,
+ final HttpParams params) {
+ return new DefaultHttpResponseParser(buffer, null, responseFactory, params);
+ }
+
+ /**
+ * Creates an instance of {@link HttpMessageWriter} to be used for
+ * writing out HTTP requests sent over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a different implementation of the {@link HttpMessageWriter} interface or
+ * to pass a different implementation of
+ * {@link ch.boye.httpclientandroidlib.message.LineFormatter} to the the default implementation
+ * {@link HttpRequestWriter}.
+ *
+ * @param buffer the session output buffer
+ * @param params HTTP parameters
+ * @return HTTP message writer
+ */
+ protected HttpMessageWriter<HttpRequest> createRequestWriter(
+ final SessionOutputBuffer buffer,
+ final HttpParams params) {
+ return new HttpRequestWriter(buffer, null, params);
+ }
+
+ /**
+ * @since 4.1
+ */
+ protected HttpConnectionMetricsImpl createConnectionMetrics(
+ final HttpTransportMetrics inTransportMetric,
+ final HttpTransportMetrics outTransportMetric) {
+ return new HttpConnectionMetricsImpl(inTransportMetric, outTransportMetric);
+ }
+
+ /**
+ * Initializes this connection object with {@link SessionInputBuffer} and
+ * {@link SessionOutputBuffer} instances to be used for sending and
+ * receiving data. These session buffers can be bound to any arbitrary
+ * physical output medium.
+ * <p>
+ * This method will invoke {@link #createHttpResponseFactory()},
+ * {@link #createRequestWriter(SessionOutputBuffer, HttpParams)}
+ * and {@link #createResponseParser(SessionInputBuffer, HttpResponseFactory, HttpParams)}
+ * methods to initialize HTTP request writer and response parser for this
+ * connection.
+ *
+ * @param inbuffer the session input buffer.
+ * @param outbuffer the session output buffer.
+ * @param params HTTP parameters.
+ */
+ protected void init(
+ final SessionInputBuffer inbuffer,
+ final SessionOutputBuffer outbuffer,
+ final HttpParams params) {
+ this.inbuffer = Args.notNull(inbuffer, "Input session buffer");
+ this.outbuffer = Args.notNull(outbuffer, "Output session buffer");
+ if (inbuffer instanceof EofSensor) {
+ this.eofSensor = (EofSensor) inbuffer;
+ }
+ this.responseParser = createResponseParser(
+ inbuffer,
+ createHttpResponseFactory(),
+ params);
+ this.requestWriter = createRequestWriter(
+ outbuffer, params);
+ this.metrics = createConnectionMetrics(
+ inbuffer.getMetrics(),
+ outbuffer.getMetrics());
+ }
+
+ public boolean isResponseAvailable(final int timeout) throws IOException {
+ assertOpen();
+ try {
+ return this.inbuffer.isDataAvailable(timeout);
+ } catch (final SocketTimeoutException ex) {
+ return false;
+ }
+ }
+
+ public void sendRequestHeader(final HttpRequest request)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ assertOpen();
+ this.requestWriter.write(request);
+ this.metrics.incrementRequestCount();
+ }
+
+ public void sendRequestEntity(final HttpEntityEnclosingRequest request)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ assertOpen();
+ if (request.getEntity() == null) {
+ return;
+ }
+ this.entityserializer.serialize(
+ this.outbuffer,
+ request,
+ request.getEntity());
+ }
+
+ protected void doFlush() throws IOException {
+ this.outbuffer.flush();
+ }
+
+ public void flush() throws IOException {
+ assertOpen();
+ doFlush();
+ }
+
+ public HttpResponse receiveResponseHeader()
+ throws HttpException, IOException {
+ assertOpen();
+ final HttpResponse response = this.responseParser.parse();
+ if (response.getStatusLine().getStatusCode() >= HttpStatus.SC_OK) {
+ this.metrics.incrementResponseCount();
+ }
+ return response;
+ }
+
+ public void receiveResponseEntity(final HttpResponse response)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ assertOpen();
+ final HttpEntity entity = this.entitydeserializer.deserialize(this.inbuffer, response);
+ response.setEntity(entity);
+ }
+
+ protected boolean isEof() {
+ return this.eofSensor != null && this.eofSensor.isEof();
+ }
+
+ public boolean isStale() {
+ if (!isOpen()) {
+ return true;
+ }
+ if (isEof()) {
+ return true;
+ }
+ try {
+ this.inbuffer.isDataAvailable(1);
+ return isEof();
+ } catch (final SocketTimeoutException ex) {
+ return false;
+ } catch (final IOException ex) {
+ return true;
+ }
+ }
+
+ public HttpConnectionMetrics getMetrics() {
+ return this.metrics;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpServerConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpServerConnection.java
new file mode 100644
index 000000000..e9e67e5b1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/AbstractHttpServerConnection.java
@@ -0,0 +1,310 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestFactory;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpServerConnection;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.impl.entity.DisallowIdentityContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.entity.EntityDeserializer;
+import ch.boye.httpclientandroidlib.impl.entity.EntitySerializer;
+import ch.boye.httpclientandroidlib.impl.entity.LaxContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.entity.StrictContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.io.DefaultHttpRequestParser;
+import ch.boye.httpclientandroidlib.impl.io.HttpResponseWriter;
+import ch.boye.httpclientandroidlib.io.EofSensor;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriter;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Abstract server-side HTTP connection capable of transmitting and receiving
+ * data using arbitrary {@link SessionInputBuffer} and
+ * {@link SessionOutputBuffer} implementations.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultBHttpServerConnection}
+ */
+@NotThreadSafe
+@Deprecated
+public abstract class AbstractHttpServerConnection implements HttpServerConnection {
+
+ private final EntitySerializer entityserializer;
+ private final EntityDeserializer entitydeserializer;
+
+ private SessionInputBuffer inbuffer = null;
+ private SessionOutputBuffer outbuffer = null;
+ private EofSensor eofSensor = null;
+ private HttpMessageParser<HttpRequest> requestParser = null;
+ private HttpMessageWriter<HttpResponse> responseWriter = null;
+ private HttpConnectionMetricsImpl metrics = null;
+
+ /**
+ * Creates an instance of this class.
+ * <p>
+ * This constructor will invoke {@link #createEntityDeserializer()}
+ * and {@link #createEntitySerializer()} methods in order to initialize
+ * HTTP entity serializer and deserializer implementations for this
+ * connection.
+ */
+ public AbstractHttpServerConnection() {
+ super();
+ this.entityserializer = createEntitySerializer();
+ this.entitydeserializer = createEntityDeserializer();
+ }
+
+ /**
+ * Asserts if the connection is open.
+ *
+ * @throws IllegalStateException if the connection is not open.
+ */
+ protected abstract void assertOpen() throws IllegalStateException;
+
+ /**
+ * Creates an instance of {@link EntityDeserializer} with the
+ * {@link LaxContentLengthStrategy} implementation to be used for
+ * de-serializing entities received over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to create
+ * instances of {@link EntityDeserializer} using a custom
+ * {@link ch.boye.httpclientandroidlib.entity.ContentLengthStrategy}.
+ *
+ * @return HTTP entity deserializer
+ */
+ protected EntityDeserializer createEntityDeserializer() {
+ return new EntityDeserializer(new DisallowIdentityContentLengthStrategy(
+ new LaxContentLengthStrategy(0)));
+ }
+
+ /**
+ * Creates an instance of {@link EntitySerializer} with the
+ * {@link StrictContentLengthStrategy} implementation to be used for
+ * serializing HTTP entities sent over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to create
+ * instances of {@link EntitySerializer} using a custom
+ * {@link ch.boye.httpclientandroidlib.entity.ContentLengthStrategy}.
+ *
+ * @return HTTP entity serialzier.
+ */
+ protected EntitySerializer createEntitySerializer() {
+ return new EntitySerializer(new StrictContentLengthStrategy());
+ }
+
+ /**
+ * Creates an instance of {@link DefaultHttpRequestFactory} to be used
+ * for creating {@link HttpRequest} objects received by over this
+ * connection.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a different implementation of the {@link HttpRequestFactory} interface.
+ *
+ * @return HTTP request factory.
+ */
+ protected HttpRequestFactory createHttpRequestFactory() {
+ return DefaultHttpRequestFactory.INSTANCE;
+ }
+
+ /**
+ * Creates an instance of {@link HttpMessageParser} to be used for parsing
+ * HTTP requests received over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a different implementation of the {@link HttpMessageParser} interface or
+ * to pass a different implementation of the
+ * {@link ch.boye.httpclientandroidlib.message.LineParser} to the
+ * {@link DefaultHttpRequestParser} constructor.
+ *
+ * @param buffer the session input buffer.
+ * @param requestFactory the HTTP request factory.
+ * @param params HTTP parameters.
+ * @return HTTP message parser.
+ */
+ protected HttpMessageParser<HttpRequest> createRequestParser(
+ final SessionInputBuffer buffer,
+ final HttpRequestFactory requestFactory,
+ final HttpParams params) {
+ return new DefaultHttpRequestParser(buffer, null, requestFactory, params);
+ }
+
+ /**
+ * Creates an instance of {@link HttpMessageWriter} to be used for
+ * writing out HTTP responses sent over this connection.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a different implementation of the {@link HttpMessageWriter} interface or
+ * to pass a different implementation of
+ * {@link ch.boye.httpclientandroidlib.message.LineFormatter} to the the default
+ * implementation {@link HttpResponseWriter}.
+ *
+ * @param buffer the session output buffer
+ * @param params HTTP parameters
+ * @return HTTP message writer
+ */
+ protected HttpMessageWriter<HttpResponse> createResponseWriter(
+ final SessionOutputBuffer buffer,
+ final HttpParams params) {
+ return new HttpResponseWriter(buffer, null, params);
+ }
+
+ /**
+ * @since 4.1
+ */
+ protected HttpConnectionMetricsImpl createConnectionMetrics(
+ final HttpTransportMetrics inTransportMetric,
+ final HttpTransportMetrics outTransportMetric) {
+ return new HttpConnectionMetricsImpl(inTransportMetric, outTransportMetric);
+ }
+
+ /**
+ * Initializes this connection object with {@link SessionInputBuffer} and
+ * {@link SessionOutputBuffer} instances to be used for sending and
+ * receiving data. These session buffers can be bound to any arbitrary
+ * physical output medium.
+ * <p>
+ * This method will invoke {@link #createHttpRequestFactory},
+ * {@link #createRequestParser(SessionInputBuffer, HttpRequestFactory, HttpParams)}
+ * and {@link #createResponseWriter(SessionOutputBuffer, HttpParams)}
+ * methods to initialize HTTP request parser and response writer for this
+ * connection.
+ *
+ * @param inbuffer the session input buffer.
+ * @param outbuffer the session output buffer.
+ * @param params HTTP parameters.
+ */
+ protected void init(
+ final SessionInputBuffer inbuffer,
+ final SessionOutputBuffer outbuffer,
+ final HttpParams params) {
+ this.inbuffer = Args.notNull(inbuffer, "Input session buffer");
+ this.outbuffer = Args.notNull(outbuffer, "Output session buffer");
+ if (inbuffer instanceof EofSensor) {
+ this.eofSensor = (EofSensor) inbuffer;
+ }
+ this.requestParser = createRequestParser(
+ inbuffer,
+ createHttpRequestFactory(),
+ params);
+ this.responseWriter = createResponseWriter(
+ outbuffer, params);
+ this.metrics = createConnectionMetrics(
+ inbuffer.getMetrics(),
+ outbuffer.getMetrics());
+ }
+
+ public HttpRequest receiveRequestHeader()
+ throws HttpException, IOException {
+ assertOpen();
+ final HttpRequest request = this.requestParser.parse();
+ this.metrics.incrementRequestCount();
+ return request;
+ }
+
+ public void receiveRequestEntity(final HttpEntityEnclosingRequest request)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ assertOpen();
+ final HttpEntity entity = this.entitydeserializer.deserialize(this.inbuffer, request);
+ request.setEntity(entity);
+ }
+
+ protected void doFlush() throws IOException {
+ this.outbuffer.flush();
+ }
+
+ public void flush() throws IOException {
+ assertOpen();
+ doFlush();
+ }
+
+ public void sendResponseHeader(final HttpResponse response)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ assertOpen();
+ this.responseWriter.write(response);
+ if (response.getStatusLine().getStatusCode() >= 200) {
+ this.metrics.incrementResponseCount();
+ }
+ }
+
+ public void sendResponseEntity(final HttpResponse response)
+ throws HttpException, IOException {
+ if (response.getEntity() == null) {
+ return;
+ }
+ this.entityserializer.serialize(
+ this.outbuffer,
+ response,
+ response.getEntity());
+ }
+
+ protected boolean isEof() {
+ return this.eofSensor != null && this.eofSensor.isEof();
+ }
+
+ public boolean isStale() {
+ if (!isOpen()) {
+ return true;
+ }
+ if (isEof()) {
+ return true;
+ }
+ try {
+ this.inbuffer.isDataAvailable(1);
+ return isEof();
+ } catch (final IOException ex) {
+ return true;
+ }
+ }
+
+ public HttpConnectionMetrics getMetrics() {
+ return this.metrics;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/BHttpConnectionBase.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/BHttpConnectionBase.java
new file mode 100644
index 000000000..2215aa6e2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/BHttpConnectionBase.java
@@ -0,0 +1,393 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpConnection;
+import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpInetConnection;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.entity.BasicHttpEntity;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.entity.LaxContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.entity.StrictContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.io.ChunkedInputStream;
+import ch.boye.httpclientandroidlib.impl.io.ChunkedOutputStream;
+import ch.boye.httpclientandroidlib.impl.io.ContentLengthInputStream;
+import ch.boye.httpclientandroidlib.impl.io.ContentLengthOutputStream;
+import ch.boye.httpclientandroidlib.impl.io.HttpTransportMetricsImpl;
+import ch.boye.httpclientandroidlib.impl.io.IdentityInputStream;
+import ch.boye.httpclientandroidlib.impl.io.IdentityOutputStream;
+import ch.boye.httpclientandroidlib.impl.io.SessionInputBufferImpl;
+import ch.boye.httpclientandroidlib.impl.io.SessionOutputBufferImpl;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.NetUtils;
+
+/**
+ * This class serves as a base for all {@link HttpConnection} implementations and provides
+ * functionality common to both client and server HTTP connections.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BHttpConnectionBase implements HttpConnection, HttpInetConnection {
+
+ private final SessionInputBufferImpl inbuffer;
+ private final SessionOutputBufferImpl outbuffer;
+ private final HttpConnectionMetricsImpl connMetrics;
+ private final ContentLengthStrategy incomingContentStrategy;
+ private final ContentLengthStrategy outgoingContentStrategy;
+
+ private volatile boolean open;
+ private volatile Socket socket;
+
+ /**
+ * Creates new instance of BHttpConnectionBase.
+ *
+ * @param buffersize buffer size. Must be a positive number.
+ * @param fragmentSizeHint fragment size hint.
+ * @param chardecoder decoder to be used for decoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for byte to char conversion.
+ * @param charencoder encoder to be used for encoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for char to byte conversion.
+ * @param constraints Message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ * @param incomingContentStrategy incoming content length strategy. If <code>null</code>
+ * {@link LaxContentLengthStrategy#INSTANCE} will be used.
+ * @param outgoingContentStrategy outgoing content length strategy. If <code>null</code>
+ * {@link StrictContentLengthStrategy#INSTANCE} will be used.
+ */
+ protected BHttpConnectionBase(
+ final int buffersize,
+ final int fragmentSizeHint,
+ final CharsetDecoder chardecoder,
+ final CharsetEncoder charencoder,
+ final MessageConstraints constraints,
+ final ContentLengthStrategy incomingContentStrategy,
+ final ContentLengthStrategy outgoingContentStrategy) {
+ super();
+ Args.positive(buffersize, "Buffer size");
+ final HttpTransportMetricsImpl inTransportMetrics = new HttpTransportMetricsImpl();
+ final HttpTransportMetricsImpl outTransportMetrics = new HttpTransportMetricsImpl();
+ this.inbuffer = new SessionInputBufferImpl(inTransportMetrics, buffersize, -1,
+ constraints != null ? constraints : MessageConstraints.DEFAULT, chardecoder);
+ this.outbuffer = new SessionOutputBufferImpl(outTransportMetrics, buffersize, fragmentSizeHint,
+ charencoder);
+ this.connMetrics = new HttpConnectionMetricsImpl(inTransportMetrics, outTransportMetrics);
+ this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
+ LaxContentLengthStrategy.INSTANCE;
+ this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
+ StrictContentLengthStrategy.INSTANCE;
+ }
+
+ protected void ensureOpen() throws IOException {
+ Asserts.check(this.open, "Connection is not open");
+ if (!this.inbuffer.isBound()) {
+ this.inbuffer.bind(getSocketInputStream(this.socket));
+ }
+ if (!this.outbuffer.isBound()) {
+ this.outbuffer.bind(getSocketOutputStream(this.socket));
+ }
+ }
+
+ protected InputStream getSocketInputStream(final Socket socket) throws IOException {
+ return socket.getInputStream();
+ }
+
+ protected OutputStream getSocketOutputStream(final Socket socket) throws IOException {
+ return socket.getOutputStream();
+ }
+
+ /**
+ * Binds this connection to the given {@link Socket}. This socket will be
+ * used by the connection to send and receive data.
+ * <p/>
+ * After this method's execution the connection status will be reported
+ * as open and the {@link #isOpen()} will return <code>true</code>.
+ *
+ * @param socket the socket.
+ * @throws IOException in case of an I/O error.
+ */
+ protected void bind(final Socket socket) throws IOException {
+ Args.notNull(socket, "Socket");
+ this.socket = socket;
+ this.open = true;
+ this.inbuffer.bind(null);
+ this.outbuffer.bind(null);
+ }
+
+ protected SessionInputBuffer getSessionInputBuffer() {
+ return this.inbuffer;
+ }
+
+ protected SessionOutputBuffer getSessionOutputBuffer() {
+ return this.outbuffer;
+ }
+
+ protected void doFlush() throws IOException {
+ this.outbuffer.flush();
+ }
+
+ public boolean isOpen() {
+ return this.open;
+ }
+
+ protected Socket getSocket() {
+ return this.socket;
+ }
+
+ protected OutputStream createOutputStream(
+ final long len,
+ final SessionOutputBuffer outbuffer) {
+ if (len == ContentLengthStrategy.CHUNKED) {
+ return new ChunkedOutputStream(2048, outbuffer);
+ } else if (len == ContentLengthStrategy.IDENTITY) {
+ return new IdentityOutputStream(outbuffer);
+ } else {
+ return new ContentLengthOutputStream(outbuffer, len);
+ }
+ }
+
+ protected OutputStream prepareOutput(final HttpMessage message) throws HttpException {
+ final long len = this.outgoingContentStrategy.determineLength(message);
+ return createOutputStream(len, this.outbuffer);
+ }
+
+ protected InputStream createInputStream(
+ final long len,
+ final SessionInputBuffer inbuffer) {
+ if (len == ContentLengthStrategy.CHUNKED) {
+ return new ChunkedInputStream(inbuffer);
+ } else if (len == ContentLengthStrategy.IDENTITY) {
+ return new IdentityInputStream(inbuffer);
+ } else {
+ return new ContentLengthInputStream(inbuffer, len);
+ }
+ }
+
+ protected HttpEntity prepareInput(final HttpMessage message) throws HttpException {
+ final BasicHttpEntity entity = new BasicHttpEntity();
+
+ final long len = this.incomingContentStrategy.determineLength(message);
+ final InputStream instream = createInputStream(len, this.inbuffer);
+ if (len == ContentLengthStrategy.CHUNKED) {
+ entity.setChunked(true);
+ entity.setContentLength(-1);
+ entity.setContent(instream);
+ } else if (len == ContentLengthStrategy.IDENTITY) {
+ entity.setChunked(false);
+ entity.setContentLength(-1);
+ entity.setContent(instream);
+ } else {
+ entity.setChunked(false);
+ entity.setContentLength(len);
+ entity.setContent(instream);
+ }
+
+ final Header contentTypeHeader = message.getFirstHeader(HTTP.CONTENT_TYPE);
+ if (contentTypeHeader != null) {
+ entity.setContentType(contentTypeHeader);
+ }
+ final Header contentEncodingHeader = message.getFirstHeader(HTTP.CONTENT_ENCODING);
+ if (contentEncodingHeader != null) {
+ entity.setContentEncoding(contentEncodingHeader);
+ }
+ return entity;
+ }
+
+ public InetAddress getLocalAddress() {
+ if (this.socket != null) {
+ return this.socket.getLocalAddress();
+ } else {
+ return null;
+ }
+ }
+
+ public int getLocalPort() {
+ if (this.socket != null) {
+ return this.socket.getLocalPort();
+ } else {
+ return -1;
+ }
+ }
+
+ public InetAddress getRemoteAddress() {
+ if (this.socket != null) {
+ return this.socket.getInetAddress();
+ } else {
+ return null;
+ }
+ }
+
+ public int getRemotePort() {
+ if (this.socket != null) {
+ return this.socket.getPort();
+ } else {
+ return -1;
+ }
+ }
+
+ public void setSocketTimeout(final int timeout) {
+ if (this.socket != null) {
+ try {
+ this.socket.setSoTimeout(timeout);
+ } catch (final SocketException ignore) {
+ // It is not quite clear from the Sun's documentation if there are any
+ // other legitimate cases for a socket exception to be thrown when setting
+ // SO_TIMEOUT besides the socket being already closed
+ }
+ }
+ }
+
+ public int getSocketTimeout() {
+ if (this.socket != null) {
+ try {
+ return this.socket.getSoTimeout();
+ } catch (final SocketException ignore) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ }
+
+ public void shutdown() throws IOException {
+ this.open = false;
+ final Socket tmpsocket = this.socket;
+ if (tmpsocket != null) {
+ tmpsocket.close();
+ }
+ }
+
+ public void close() throws IOException {
+ if (!this.open) {
+ return;
+ }
+ this.open = false;
+ final Socket sock = this.socket;
+ try {
+ this.inbuffer.clear();
+ this.outbuffer.flush();
+ try {
+ try {
+ sock.shutdownOutput();
+ } catch (final IOException ignore) {
+ }
+ try {
+ sock.shutdownInput();
+ } catch (final IOException ignore) {
+ }
+ } catch (final UnsupportedOperationException ignore) {
+ // if one isn't supported, the other one isn't either
+ }
+ } finally {
+ sock.close();
+ }
+ }
+
+ private int fillInputBuffer(final int timeout) throws IOException {
+ final int oldtimeout = this.socket.getSoTimeout();
+ try {
+ this.socket.setSoTimeout(timeout);
+ return this.inbuffer.fillBuffer();
+ } finally {
+ this.socket.setSoTimeout(oldtimeout);
+ }
+ }
+
+ protected boolean awaitInput(final int timeout) throws IOException {
+ if (this.inbuffer.hasBufferedData()) {
+ return true;
+ }
+ fillInputBuffer(timeout);
+ return this.inbuffer.hasBufferedData();
+ }
+
+ public boolean isStale() {
+ if (!isOpen()) {
+ return true;
+ }
+ try {
+ final int bytesRead = fillInputBuffer(1);
+ return bytesRead < 0;
+ } catch (final SocketTimeoutException ex) {
+ return false;
+ } catch (final IOException ex) {
+ return true;
+ }
+ }
+
+ protected void incrementRequestCount() {
+ this.connMetrics.incrementRequestCount();
+ }
+
+ protected void incrementResponseCount() {
+ this.connMetrics.incrementResponseCount();
+ }
+
+ public HttpConnectionMetrics getMetrics() {
+ return this.connMetrics;
+ }
+
+ @Override
+ public String toString() {
+ if (this.socket != null) {
+ final StringBuilder buffer = new StringBuilder();
+ final SocketAddress remoteAddress = this.socket.getRemoteSocketAddress();
+ final SocketAddress localAddress = this.socket.getLocalSocketAddress();
+ if (remoteAddress != null && localAddress != null) {
+ NetUtils.formatAddress(buffer, localAddress);
+ buffer.append("<->");
+ NetUtils.formatAddress(buffer, remoteAddress);
+ }
+ return buffer.toString();
+ } else {
+ return "[Not bound]";
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/ConnSupport.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/ConnSupport.java
new file mode 100644
index 000000000..ba82a2a7c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/ConnSupport.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl;
+
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * Connection support methods.
+ *
+ * @since 4.3
+ */
+public final class ConnSupport {
+
+ public static CharsetDecoder createDecoder(final ConnectionConfig cconfig) {
+ if (cconfig == null) {
+ return null;
+ }
+ final Charset charset = cconfig.getCharset();
+ final CodingErrorAction malformed = cconfig.getMalformedInputAction();
+ final CodingErrorAction unmappable = cconfig.getUnmappableInputAction();
+ if (charset != null) {
+ return charset.newDecoder()
+ .onMalformedInput(malformed != null ? malformed : CodingErrorAction.REPORT)
+ .onUnmappableCharacter(unmappable != null ? unmappable: CodingErrorAction.REPORT);
+ } else {
+ return null;
+ }
+ }
+
+ public static CharsetEncoder createEncoder(final ConnectionConfig cconfig) {
+ if (cconfig == null) {
+ return null;
+ }
+ final Charset charset = cconfig.getCharset();
+ if (charset != null) {
+ final CodingErrorAction malformed = cconfig.getMalformedInputAction();
+ final CodingErrorAction unmappable = cconfig.getUnmappableInputAction();
+ return charset.newEncoder()
+ .onMalformedInput(malformed != null ? malformed : CodingErrorAction.REPORT)
+ .onUnmappableCharacter(unmappable != null ? unmappable: CodingErrorAction.REPORT);
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnection.java
new file mode 100644
index 000000000..9627e53f2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnection.java
@@ -0,0 +1,182 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.io.DefaultHttpRequestWriterFactory;
+import ch.boye.httpclientandroidlib.impl.io.DefaultHttpResponseParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriter;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of {@link HttpClientConnection}.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class DefaultBHttpClientConnection extends BHttpConnectionBase
+ implements HttpClientConnection {
+
+ private final HttpMessageParser<HttpResponse> responseParser;
+ private final HttpMessageWriter<HttpRequest> requestWriter;
+
+ /**
+ * Creates new instance of DefaultBHttpClientConnection.
+ *
+ * @param buffersize buffer size. Must be a positive number.
+ * @param fragmentSizeHint fragment size hint.
+ * @param chardecoder decoder to be used for decoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for byte to char conversion.
+ * @param charencoder encoder to be used for encoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for char to byte conversion.
+ * @param constraints Message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ * @param incomingContentStrategy incoming content length strategy. If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.impl.entity.LaxContentLengthStrategy#INSTANCE} will be used.
+ * @param outgoingContentStrategy outgoing content length strategy. If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.impl.entity.StrictContentLengthStrategy#INSTANCE} will be used.
+ * @param requestWriterFactory request writer factory. If <code>null</code>
+ * {@link DefaultHttpRequestWriterFactory#INSTANCE} will be used.
+ * @param responseParserFactory response parser factory. If <code>null</code>
+ * {@link DefaultHttpResponseParserFactory#INSTANCE} will be used.
+ */
+ public DefaultBHttpClientConnection(
+ final int buffersize,
+ final int fragmentSizeHint,
+ final CharsetDecoder chardecoder,
+ final CharsetEncoder charencoder,
+ final MessageConstraints constraints,
+ final ContentLengthStrategy incomingContentStrategy,
+ final ContentLengthStrategy outgoingContentStrategy,
+ final HttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+ final HttpMessageParserFactory<HttpResponse> responseParserFactory) {
+ super(buffersize, fragmentSizeHint, chardecoder, charencoder,
+ constraints, incomingContentStrategy, outgoingContentStrategy);
+ this.requestWriter = (requestWriterFactory != null ? requestWriterFactory :
+ DefaultHttpRequestWriterFactory.INSTANCE).create(getSessionOutputBuffer());
+ this.responseParser = (responseParserFactory != null ? responseParserFactory :
+ DefaultHttpResponseParserFactory.INSTANCE).create(getSessionInputBuffer(), constraints);
+ }
+
+ public DefaultBHttpClientConnection(
+ final int buffersize,
+ final CharsetDecoder chardecoder,
+ final CharsetEncoder charencoder,
+ final MessageConstraints constraints) {
+ this(buffersize, buffersize, chardecoder, charencoder, constraints, null, null, null, null);
+ }
+
+ public DefaultBHttpClientConnection(final int buffersize) {
+ this(buffersize, buffersize, null, null, null, null, null, null, null);
+ }
+
+ protected void onResponseReceived(final HttpResponse response) {
+ }
+
+ protected void onRequestSubmitted(final HttpRequest request) {
+ }
+
+ @Override
+ public void bind(final Socket socket) throws IOException {
+ super.bind(socket);
+ }
+
+ public boolean isResponseAvailable(final int timeout) throws IOException {
+ ensureOpen();
+ try {
+ return awaitInput(timeout);
+ } catch (final SocketTimeoutException ex) {
+ return false;
+ }
+ }
+
+ public void sendRequestHeader(final HttpRequest request)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ ensureOpen();
+ this.requestWriter.write(request);
+ onRequestSubmitted(request);
+ incrementRequestCount();
+ }
+
+ public void sendRequestEntity(final HttpEntityEnclosingRequest request)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ ensureOpen();
+ final HttpEntity entity = request.getEntity();
+ if (entity == null) {
+ return;
+ }
+ final OutputStream outstream = prepareOutput(request);
+ entity.writeTo(outstream);
+ outstream.close();
+ }
+
+ public HttpResponse receiveResponseHeader() throws HttpException, IOException {
+ ensureOpen();
+ final HttpResponse response = this.responseParser.parse();
+ onResponseReceived(response);
+ if (response.getStatusLine().getStatusCode() >= HttpStatus.SC_OK) {
+ incrementResponseCount();
+ }
+ return response;
+ }
+
+ public void receiveResponseEntity(
+ final HttpResponse response) throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ ensureOpen();
+ final HttpEntity entity = prepareInput(response);
+ response.setEntity(entity);
+ }
+
+ public void flush() throws IOException {
+ ensureOpen();
+ doFlush();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnectionFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnectionFactory.java
new file mode 100644
index 000000000..f337339c3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpClientConnectionFactory.java
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import ch.boye.httpclientandroidlib.HttpConnectionFactory;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+
+import java.io.IOException;
+import java.net.Socket;
+
+/**
+ * Default factory for {@link ch.boye.httpclientandroidlib.HttpClientConnection}s.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultBHttpClientConnectionFactory
+ implements HttpConnectionFactory<DefaultBHttpClientConnection> {
+
+ public static final DefaultBHttpClientConnectionFactory INSTANCE = new DefaultBHttpClientConnectionFactory();
+
+ private final ConnectionConfig cconfig;
+ private final ContentLengthStrategy incomingContentStrategy;
+ private final ContentLengthStrategy outgoingContentStrategy;
+ private final HttpMessageWriterFactory<HttpRequest> requestWriterFactory;
+ private final HttpMessageParserFactory<HttpResponse> responseParserFactory;
+
+ public DefaultBHttpClientConnectionFactory(
+ final ConnectionConfig cconfig,
+ final ContentLengthStrategy incomingContentStrategy,
+ final ContentLengthStrategy outgoingContentStrategy,
+ final HttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+ final HttpMessageParserFactory<HttpResponse> responseParserFactory) {
+ super();
+ this.cconfig = cconfig != null ? cconfig : ConnectionConfig.DEFAULT;
+ this.incomingContentStrategy = incomingContentStrategy;
+ this.outgoingContentStrategy = outgoingContentStrategy;
+ this.requestWriterFactory = requestWriterFactory;
+ this.responseParserFactory = responseParserFactory;
+ }
+
+ public DefaultBHttpClientConnectionFactory(
+ final ConnectionConfig cconfig,
+ final HttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+ final HttpMessageParserFactory<HttpResponse> responseParserFactory) {
+ this(cconfig, null, null, requestWriterFactory, responseParserFactory);
+ }
+
+ public DefaultBHttpClientConnectionFactory(final ConnectionConfig cconfig) {
+ this(cconfig, null, null, null, null);
+ }
+
+ public DefaultBHttpClientConnectionFactory() {
+ this(null, null, null, null, null);
+ }
+
+ public DefaultBHttpClientConnection createConnection(final Socket socket) throws IOException {
+ final DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(
+ this.cconfig.getBufferSize(),
+ this.cconfig.getFragmentSizeHint(),
+ ConnSupport.createDecoder(this.cconfig),
+ ConnSupport.createEncoder(this.cconfig),
+ this.cconfig.getMessageConstraints(),
+ this.incomingContentStrategy,
+ this.outgoingContentStrategy,
+ this.requestWriterFactory,
+ this.responseParserFactory);
+ conn.bind(socket);
+ return conn;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnection.java
new file mode 100644
index 000000000..6ee4fb740
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnection.java
@@ -0,0 +1,174 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpServerConnection;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.entity.DisallowIdentityContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.io.DefaultHttpRequestParserFactory;
+import ch.boye.httpclientandroidlib.impl.io.DefaultHttpResponseWriterFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriter;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of {@link HttpServerConnection}.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class DefaultBHttpServerConnection extends BHttpConnectionBase
+ implements HttpServerConnection {
+
+ private final HttpMessageParser<HttpRequest> requestParser;
+ private final HttpMessageWriter<HttpResponse> responseWriter;
+
+ /**
+ * Creates new instance of DefaultBHttpServerConnection.
+ *
+ * @param buffersize buffer size. Must be a positive number.
+ * @param fragmentSizeHint fragment size hint.
+ * @param chardecoder decoder to be used for decoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for byte to char conversion.
+ * @param charencoder encoder to be used for encoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for char to byte conversion.
+ * @param constraints Message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ * @param incomingContentStrategy incoming content length strategy. If <code>null</code>
+ * {@link DisallowIdentityContentLengthStrategy#INSTANCE} will be used.
+ * @param outgoingContentStrategy outgoing content length strategy. If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.impl.entity.StrictContentLengthStrategy#INSTANCE} will be used.
+ * @param requestParserFactory request parser factory. If <code>null</code>
+ * {@link DefaultHttpRequestParserFactory#INSTANCE} will be used.
+ * @param responseWriterFactory response writer factory. If <code>null</code>
+ * {@link DefaultHttpResponseWriterFactory#INSTANCE} will be used.
+ */
+ public DefaultBHttpServerConnection(
+ final int buffersize,
+ final int fragmentSizeHint,
+ final CharsetDecoder chardecoder,
+ final CharsetEncoder charencoder,
+ final MessageConstraints constraints,
+ final ContentLengthStrategy incomingContentStrategy,
+ final ContentLengthStrategy outgoingContentStrategy,
+ final HttpMessageParserFactory<HttpRequest> requestParserFactory,
+ final HttpMessageWriterFactory<HttpResponse> responseWriterFactory) {
+ super(buffersize, fragmentSizeHint, chardecoder, charencoder, constraints,
+ incomingContentStrategy != null ? incomingContentStrategy :
+ DisallowIdentityContentLengthStrategy.INSTANCE, outgoingContentStrategy);
+ this.requestParser = (requestParserFactory != null ? requestParserFactory :
+ DefaultHttpRequestParserFactory.INSTANCE).create(getSessionInputBuffer(), constraints);
+ this.responseWriter = (responseWriterFactory != null ? responseWriterFactory :
+ DefaultHttpResponseWriterFactory.INSTANCE).create(getSessionOutputBuffer());
+ }
+
+ public DefaultBHttpServerConnection(
+ final int buffersize,
+ final CharsetDecoder chardecoder,
+ final CharsetEncoder charencoder,
+ final MessageConstraints constraints) {
+ this(buffersize, buffersize, chardecoder, charencoder, constraints, null, null, null, null);
+ }
+
+ public DefaultBHttpServerConnection(final int buffersize) {
+ this(buffersize, buffersize, null, null, null, null, null, null, null);
+ }
+
+ protected void onRequestReceived(final HttpRequest request) {
+ }
+
+ protected void onResponseSubmitted(final HttpResponse response) {
+ }
+
+ @Override
+ public void bind(final Socket socket) throws IOException {
+ super.bind(socket);
+ }
+
+ public HttpRequest receiveRequestHeader()
+ throws HttpException, IOException {
+ ensureOpen();
+ final HttpRequest request = this.requestParser.parse();
+ onRequestReceived(request);
+ incrementRequestCount();
+ return request;
+ }
+
+ public void receiveRequestEntity(final HttpEntityEnclosingRequest request)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ ensureOpen();
+ final HttpEntity entity = prepareInput(request);
+ request.setEntity(entity);
+ }
+
+ public void sendResponseHeader(final HttpResponse response)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ ensureOpen();
+ this.responseWriter.write(response);
+ onResponseSubmitted(response);
+ if (response.getStatusLine().getStatusCode() >= 200) {
+ incrementResponseCount();
+ }
+ }
+
+ public void sendResponseEntity(final HttpResponse response)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ ensureOpen();
+ final HttpEntity entity = response.getEntity();
+ if (entity == null) {
+ return;
+ }
+ final OutputStream outstream = prepareOutput(response);
+ entity.writeTo(outstream);
+ outstream.close();
+ }
+
+ public void flush() throws IOException {
+ ensureOpen();
+ doFlush();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnectionFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnectionFactory.java
new file mode 100644
index 000000000..a312320aa
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultBHttpServerConnectionFactory.java
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import ch.boye.httpclientandroidlib.HttpConnectionFactory;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+
+import java.io.IOException;
+import java.net.Socket;
+
+/**
+ * Default factory for {@link ch.boye.httpclientandroidlib.HttpServerConnection}s.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultBHttpServerConnectionFactory
+ implements HttpConnectionFactory<DefaultBHttpServerConnection> {
+
+ public static final DefaultBHttpServerConnectionFactory INSTANCE = new DefaultBHttpServerConnectionFactory();
+
+ private final ConnectionConfig cconfig;
+ private final ContentLengthStrategy incomingContentStrategy;
+ private final ContentLengthStrategy outgoingContentStrategy;
+ private final HttpMessageParserFactory<HttpRequest> requestParserFactory;
+ private final HttpMessageWriterFactory<HttpResponse> responseWriterFactory;
+
+ public DefaultBHttpServerConnectionFactory(
+ final ConnectionConfig cconfig,
+ final ContentLengthStrategy incomingContentStrategy,
+ final ContentLengthStrategy outgoingContentStrategy,
+ final HttpMessageParserFactory<HttpRequest> requestParserFactory,
+ final HttpMessageWriterFactory<HttpResponse> responseWriterFactory) {
+ super();
+ this.cconfig = cconfig != null ? cconfig : ConnectionConfig.DEFAULT;
+ this.incomingContentStrategy = incomingContentStrategy;
+ this.outgoingContentStrategy = outgoingContentStrategy;
+ this.requestParserFactory = requestParserFactory;
+ this.responseWriterFactory = responseWriterFactory;
+ }
+
+ public DefaultBHttpServerConnectionFactory(
+ final ConnectionConfig cconfig,
+ final HttpMessageParserFactory<HttpRequest> requestParserFactory,
+ final HttpMessageWriterFactory<HttpResponse> responseWriterFactory) {
+ this(cconfig, null, null, requestParserFactory, responseWriterFactory);
+ }
+
+ public DefaultBHttpServerConnectionFactory(final ConnectionConfig cconfig) {
+ this(cconfig, null, null, null, null);
+ }
+
+ public DefaultBHttpServerConnectionFactory() {
+ this(null, null, null, null, null);
+ }
+
+ public DefaultBHttpServerConnection createConnection(final Socket socket) throws IOException {
+ final DefaultBHttpServerConnection conn = new DefaultBHttpServerConnection(
+ this.cconfig.getBufferSize(),
+ this.cconfig.getFragmentSizeHint(),
+ ConnSupport.createDecoder(this.cconfig),
+ ConnSupport.createEncoder(this.cconfig),
+ this.cconfig.getMessageConstraints(),
+ this.incomingContentStrategy,
+ this.outgoingContentStrategy,
+ this.requestParserFactory,
+ this.responseWriterFactory);
+ conn.bind(socket);
+ return conn;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java
new file mode 100644
index 000000000..b58127e5f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java
@@ -0,0 +1,189 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.TokenIterator;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.message.BasicTokenIterator;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of a strategy deciding about connection re-use.
+ * The default implementation first checks some basics, for example
+ * whether the connection is still open or whether the end of the
+ * request entity can be determined without closing the connection.
+ * If these checks pass, the tokens in the <code>Connection</code> header will
+ * be examined. In the absence of a <code>Connection</code> header, the
+ * non-standard but commonly used <code>Proxy-Connection</code> header takes
+ * it's role. A token <code>close</code> indicates that the connection cannot
+ * be reused. If there is no such token, a token <code>keep-alive</code>
+ * indicates that the connection should be re-used. If neither token is found,
+ * or if there are no <code>Connection</code> headers, the default policy for
+ * the HTTP version is applied. Since <code>HTTP/1.1</code>, connections are
+ * re-used by default. Up until <code>HTTP/1.0</code>, connections are not
+ * re-used by default.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class DefaultConnectionReuseStrategy implements ConnectionReuseStrategy {
+
+ public static final DefaultConnectionReuseStrategy INSTANCE = new DefaultConnectionReuseStrategy();
+
+ public DefaultConnectionReuseStrategy() {
+ super();
+ }
+
+ // see interface ConnectionReuseStrategy
+ public boolean keepAlive(final HttpResponse response,
+ final HttpContext context) {
+ Args.notNull(response, "HTTP response");
+ Args.notNull(context, "HTTP context");
+
+ // Check for a self-terminating entity. If the end of the entity will
+ // be indicated by closing the connection, there is no keep-alive.
+ final ProtocolVersion ver = response.getStatusLine().getProtocolVersion();
+ final Header teh = response.getFirstHeader(HTTP.TRANSFER_ENCODING);
+ if (teh != null) {
+ if (!HTTP.CHUNK_CODING.equalsIgnoreCase(teh.getValue())) {
+ return false;
+ }
+ } else {
+ if (canResponseHaveBody(response)) {
+ final Header[] clhs = response.getHeaders(HTTP.CONTENT_LEN);
+ // Do not reuse if not properly content-length delimited
+ if (clhs.length == 1) {
+ final Header clh = clhs[0];
+ try {
+ final int contentLen = Integer.parseInt(clh.getValue());
+ if (contentLen < 0) {
+ return false;
+ }
+ } catch (final NumberFormatException ex) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
+ // Check for the "Connection" header. If that is absent, check for
+ // the "Proxy-Connection" header. The latter is an unspecified and
+ // broken but unfortunately common extension of HTTP.
+ HeaderIterator hit = response.headerIterator(HTTP.CONN_DIRECTIVE);
+ if (!hit.hasNext()) {
+ hit = response.headerIterator("Proxy-Connection");
+ }
+
+ // Experimental usage of the "Connection" header in HTTP/1.0 is
+ // documented in RFC 2068, section 19.7.1. A token "keep-alive" is
+ // used to indicate that the connection should be persistent.
+ // Note that the final specification of HTTP/1.1 in RFC 2616 does not
+ // include this information. Neither is the "Connection" header
+ // mentioned in RFC 1945, which informally describes HTTP/1.0.
+ //
+ // RFC 2616 specifies "close" as the only connection token with a
+ // specific meaning: it disables persistent connections.
+ //
+ // The "Proxy-Connection" header is not formally specified anywhere,
+ // but is commonly used to carry one token, "close" or "keep-alive".
+ // The "Connection" header, on the other hand, is defined as a
+ // sequence of tokens, where each token is a header name, and the
+ // token "close" has the above-mentioned additional meaning.
+ //
+ // To get through this mess, we treat the "Proxy-Connection" header
+ // in exactly the same way as the "Connection" header, but only if
+ // the latter is missing. We scan the sequence of tokens for both
+ // "close" and "keep-alive". As "close" is specified by RFC 2068,
+ // it takes precedence and indicates a non-persistent connection.
+ // If there is no "close" but a "keep-alive", we take the hint.
+
+ if (hit.hasNext()) {
+ try {
+ final TokenIterator ti = createTokenIterator(hit);
+ boolean keepalive = false;
+ while (ti.hasNext()) {
+ final String token = ti.nextToken();
+ if (HTTP.CONN_CLOSE.equalsIgnoreCase(token)) {
+ return false;
+ } else if (HTTP.CONN_KEEP_ALIVE.equalsIgnoreCase(token)) {
+ // continue the loop, there may be a "close" afterwards
+ keepalive = true;
+ }
+ }
+ if (keepalive)
+ {
+ return true;
+ // neither "close" nor "keep-alive", use default policy
+ }
+
+ } catch (final ParseException px) {
+ // invalid connection header means no persistent connection
+ // we don't have logging in HttpCore, so the exception is lost
+ return false;
+ }
+ }
+
+ // default since HTTP/1.1 is persistent, before it was non-persistent
+ return !ver.lessEquals(HttpVersion.HTTP_1_0);
+ }
+
+
+ /**
+ * Creates a token iterator from a header iterator.
+ * This method can be overridden to replace the implementation of
+ * the token iterator.
+ *
+ * @param hit the header iterator
+ *
+ * @return the token iterator
+ */
+ protected TokenIterator createTokenIterator(final HeaderIterator hit) {
+ return new BasicTokenIterator(hit);
+ }
+
+ private boolean canResponseHaveBody(final HttpResponse response) {
+ final int status = response.getStatusLine().getStatusCode();
+ return status >= HttpStatus.SC_OK
+ && status != HttpStatus.SC_NO_CONTENT
+ && status != HttpStatus.SC_NOT_MODIFIED
+ && status != HttpStatus.SC_RESET_CONTENT;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpClientConnection.java
new file mode 100644
index 000000000..adb597863
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpClientConnection.java
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of a client-side HTTP connection.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultBHttpClientConnection}
+ */
+@NotThreadSafe
+@Deprecated
+public class DefaultHttpClientConnection extends SocketHttpClientConnection {
+
+ public DefaultHttpClientConnection() {
+ super();
+ }
+
+ @Override
+ public void bind(
+ final Socket socket,
+ final HttpParams params) throws IOException {
+ Args.notNull(socket, "Socket");
+ Args.notNull(params, "HTTP parameters");
+ assertNotOpen();
+ socket.setTcpNoDelay(params.getBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true));
+ socket.setSoTimeout(params.getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0));
+ socket.setKeepAlive(params.getBooleanParameter(CoreConnectionPNames.SO_KEEPALIVE, false));
+ final int linger = params.getIntParameter(CoreConnectionPNames.SO_LINGER, -1);
+ if (linger >= 0) {
+ socket.setSoLinger(linger > 0, linger);
+ }
+ super.bind(socket, params);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpRequestFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpRequestFactory.java
new file mode 100644
index 000000000..0491e94bd
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpRequestFactory.java
@@ -0,0 +1,109 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestFactory;
+import ch.boye.httpclientandroidlib.MethodNotSupportedException;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.message.BasicHttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.message.BasicHttpRequest;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default factory for creating {@link HttpRequest} objects.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class DefaultHttpRequestFactory implements HttpRequestFactory {
+
+ public static final DefaultHttpRequestFactory INSTANCE = new DefaultHttpRequestFactory();
+
+ private static final String[] RFC2616_COMMON_METHODS = {
+ "GET"
+ };
+
+ private static final String[] RFC2616_ENTITY_ENC_METHODS = {
+ "POST",
+ "PUT"
+ };
+
+ private static final String[] RFC2616_SPECIAL_METHODS = {
+ "HEAD",
+ "OPTIONS",
+ "DELETE",
+ "TRACE",
+ "CONNECT"
+ };
+
+
+ public DefaultHttpRequestFactory() {
+ super();
+ }
+
+ private static boolean isOneOf(final String[] methods, final String method) {
+ for (final String method2 : methods) {
+ if (method2.equalsIgnoreCase(method)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public HttpRequest newHttpRequest(final RequestLine requestline)
+ throws MethodNotSupportedException {
+ Args.notNull(requestline, "Request line");
+ final String method = requestline.getMethod();
+ if (isOneOf(RFC2616_COMMON_METHODS, method)) {
+ return new BasicHttpRequest(requestline);
+ } else if (isOneOf(RFC2616_ENTITY_ENC_METHODS, method)) {
+ return new BasicHttpEntityEnclosingRequest(requestline);
+ } else if (isOneOf(RFC2616_SPECIAL_METHODS, method)) {
+ return new BasicHttpRequest(requestline);
+ } else {
+ throw new MethodNotSupportedException(method + " method not supported");
+ }
+ }
+
+ public HttpRequest newHttpRequest(final String method, final String uri)
+ throws MethodNotSupportedException {
+ if (isOneOf(RFC2616_COMMON_METHODS, method)) {
+ return new BasicHttpRequest(method, uri);
+ } else if (isOneOf(RFC2616_ENTITY_ENC_METHODS, method)) {
+ return new BasicHttpEntityEnclosingRequest(method, uri);
+ } else if (isOneOf(RFC2616_SPECIAL_METHODS, method)) {
+ return new BasicHttpRequest(method, uri);
+ } else {
+ throw new MethodNotSupportedException(method
+ + " method not supported");
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpResponseFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpResponseFactory.java
new file mode 100644
index 000000000..21511b9ff
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpResponseFactory.java
@@ -0,0 +1,109 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.ReasonPhraseCatalog;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
+import ch.boye.httpclientandroidlib.message.BasicStatusLine;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default factory for creating {@link HttpResponse} objects.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class DefaultHttpResponseFactory implements HttpResponseFactory {
+
+ public static final DefaultHttpResponseFactory INSTANCE = new DefaultHttpResponseFactory();
+
+ /** The catalog for looking up reason phrases. */
+ protected final ReasonPhraseCatalog reasonCatalog;
+
+
+ /**
+ * Creates a new response factory with the given catalog.
+ *
+ * @param catalog the catalog of reason phrases
+ */
+ public DefaultHttpResponseFactory(final ReasonPhraseCatalog catalog) {
+ this.reasonCatalog = Args.notNull(catalog, "Reason phrase catalog");
+ }
+
+ /**
+ * Creates a new response factory with the default catalog.
+ * The default catalog is {@link EnglishReasonPhraseCatalog}.
+ */
+ public DefaultHttpResponseFactory() {
+ this(EnglishReasonPhraseCatalog.INSTANCE);
+ }
+
+
+ // non-javadoc, see interface HttpResponseFactory
+ public HttpResponse newHttpResponse(
+ final ProtocolVersion ver,
+ final int status,
+ final HttpContext context) {
+ Args.notNull(ver, "HTTP version");
+ final Locale loc = determineLocale(context);
+ final String reason = this.reasonCatalog.getReason(status, loc);
+ final StatusLine statusline = new BasicStatusLine(ver, status, reason);
+ return new BasicHttpResponse(statusline, this.reasonCatalog, loc);
+ }
+
+
+ // non-javadoc, see interface HttpResponseFactory
+ public HttpResponse newHttpResponse(
+ final StatusLine statusline,
+ final HttpContext context) {
+ Args.notNull(statusline, "Status line");
+ return new BasicHttpResponse(statusline, this.reasonCatalog, determineLocale(context));
+ }
+
+ /**
+ * Determines the locale of the response.
+ * The implementation in this class always returns the default locale.
+ *
+ * @param context the context from which to determine the locale, or
+ * <code>null</code> to use the default locale
+ *
+ * @return the locale for the response, never <code>null</code>
+ */
+ protected Locale determineLocale(final HttpContext context) {
+ return Locale.getDefault();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpServerConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpServerConnection.java
new file mode 100644
index 000000000..8162e6107
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/DefaultHttpServerConnection.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of a server-side HTTP connection.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultBHttpServerConnection}
+ */
+@NotThreadSafe
+@Deprecated
+public class DefaultHttpServerConnection extends SocketHttpServerConnection {
+
+ public DefaultHttpServerConnection() {
+ super();
+ }
+
+ @Override
+ public void bind(final Socket socket, final HttpParams params) throws IOException {
+ Args.notNull(socket, "Socket");
+ Args.notNull(params, "HTTP parameters");
+ assertNotOpen();
+ socket.setTcpNoDelay(params.getBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true));
+ socket.setSoTimeout(params.getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0));
+ socket.setKeepAlive(params.getBooleanParameter(CoreConnectionPNames.SO_KEEPALIVE, false));
+ final int linger = params.getIntParameter(CoreConnectionPNames.SO_LINGER, -1);
+ if (linger >= 0) {
+ socket.setSoLinger(linger > 0, linger);
+ }
+ if (linger >= 0) {
+ socket.setSoLinger(linger > 0, linger);
+ }
+ super.bind(socket, params);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java
new file mode 100644
index 000000000..51e435c0a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java
@@ -0,0 +1,224 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.ReasonPhraseCatalog;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * English reason phrases for HTTP status codes.
+ * All status codes defined in RFC1945 (HTTP/1.0), RFC2616 (HTTP/1.1), and
+ * RFC2518 (WebDAV) are supported.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class EnglishReasonPhraseCatalog implements ReasonPhraseCatalog {
+
+ // static array with english reason phrases defined below
+
+ /**
+ * The default instance of this catalog.
+ * This catalog is thread safe, so there typically
+ * is no need to create other instances.
+ */
+ public final static EnglishReasonPhraseCatalog INSTANCE =
+ new EnglishReasonPhraseCatalog();
+
+
+ /**
+ * Restricted default constructor, for derived classes.
+ * If you need an instance of this class, use {@link #INSTANCE INSTANCE}.
+ */
+ protected EnglishReasonPhraseCatalog() {
+ // no body
+ }
+
+
+ /**
+ * Obtains the reason phrase for a status code.
+ *
+ * @param status the status code, in the range 100-599
+ * @param loc ignored
+ *
+ * @return the reason phrase, or <code>null</code>
+ */
+ public String getReason(final int status, final Locale loc) {
+ Args.check(status >= 100 && status < 600, "Unknown category for status code " + status);
+ final int category = status / 100;
+ final int subcode = status - 100*category;
+
+ String reason = null;
+ if (REASON_PHRASES[category].length > subcode) {
+ reason = REASON_PHRASES[category][subcode];
+ }
+
+ return reason;
+ }
+
+
+ /** Reason phrases lookup table. */
+ private static final String[][] REASON_PHRASES = new String[][]{
+ null,
+ new String[3], // 1xx
+ new String[8], // 2xx
+ new String[8], // 3xx
+ new String[25], // 4xx
+ new String[8] // 5xx
+ };
+
+
+
+ /**
+ * Stores the given reason phrase, by status code.
+ * Helper method to initialize the static lookup table.
+ *
+ * @param status the status code for which to define the phrase
+ * @param reason the reason phrase for this status code
+ */
+ private static void setReason(final int status, final String reason) {
+ final int category = status / 100;
+ final int subcode = status - 100*category;
+ REASON_PHRASES[category][subcode] = reason;
+ }
+
+
+ // ----------------------------------------------------- Static Initializer
+
+ /** Set up status code to "reason phrase" map. */
+ static {
+ // HTTP 1.0 Server status codes -- see RFC 1945
+ setReason(HttpStatus.SC_OK,
+ "OK");
+ setReason(HttpStatus.SC_CREATED,
+ "Created");
+ setReason(HttpStatus.SC_ACCEPTED,
+ "Accepted");
+ setReason(HttpStatus.SC_NO_CONTENT,
+ "No Content");
+ setReason(HttpStatus.SC_MOVED_PERMANENTLY,
+ "Moved Permanently");
+ setReason(HttpStatus.SC_MOVED_TEMPORARILY,
+ "Moved Temporarily");
+ setReason(HttpStatus.SC_NOT_MODIFIED,
+ "Not Modified");
+ setReason(HttpStatus.SC_BAD_REQUEST,
+ "Bad Request");
+ setReason(HttpStatus.SC_UNAUTHORIZED,
+ "Unauthorized");
+ setReason(HttpStatus.SC_FORBIDDEN,
+ "Forbidden");
+ setReason(HttpStatus.SC_NOT_FOUND,
+ "Not Found");
+ setReason(HttpStatus.SC_INTERNAL_SERVER_ERROR,
+ "Internal Server Error");
+ setReason(HttpStatus.SC_NOT_IMPLEMENTED,
+ "Not Implemented");
+ setReason(HttpStatus.SC_BAD_GATEWAY,
+ "Bad Gateway");
+ setReason(HttpStatus.SC_SERVICE_UNAVAILABLE,
+ "Service Unavailable");
+
+ // HTTP 1.1 Server status codes -- see RFC 2048
+ setReason(HttpStatus.SC_CONTINUE,
+ "Continue");
+ setReason(HttpStatus.SC_TEMPORARY_REDIRECT,
+ "Temporary Redirect");
+ setReason(HttpStatus.SC_METHOD_NOT_ALLOWED,
+ "Method Not Allowed");
+ setReason(HttpStatus.SC_CONFLICT,
+ "Conflict");
+ setReason(HttpStatus.SC_PRECONDITION_FAILED,
+ "Precondition Failed");
+ setReason(HttpStatus.SC_REQUEST_TOO_LONG,
+ "Request Too Long");
+ setReason(HttpStatus.SC_REQUEST_URI_TOO_LONG,
+ "Request-URI Too Long");
+ setReason(HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE,
+ "Unsupported Media Type");
+ setReason(HttpStatus.SC_MULTIPLE_CHOICES,
+ "Multiple Choices");
+ setReason(HttpStatus.SC_SEE_OTHER,
+ "See Other");
+ setReason(HttpStatus.SC_USE_PROXY,
+ "Use Proxy");
+ setReason(HttpStatus.SC_PAYMENT_REQUIRED,
+ "Payment Required");
+ setReason(HttpStatus.SC_NOT_ACCEPTABLE,
+ "Not Acceptable");
+ setReason(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED,
+ "Proxy Authentication Required");
+ setReason(HttpStatus.SC_REQUEST_TIMEOUT,
+ "Request Timeout");
+
+ setReason(HttpStatus.SC_SWITCHING_PROTOCOLS,
+ "Switching Protocols");
+ setReason(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION,
+ "Non Authoritative Information");
+ setReason(HttpStatus.SC_RESET_CONTENT,
+ "Reset Content");
+ setReason(HttpStatus.SC_PARTIAL_CONTENT,
+ "Partial Content");
+ setReason(HttpStatus.SC_GATEWAY_TIMEOUT,
+ "Gateway Timeout");
+ setReason(HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED,
+ "Http Version Not Supported");
+ setReason(HttpStatus.SC_GONE,
+ "Gone");
+ setReason(HttpStatus.SC_LENGTH_REQUIRED,
+ "Length Required");
+ setReason(HttpStatus.SC_REQUESTED_RANGE_NOT_SATISFIABLE,
+ "Requested Range Not Satisfiable");
+ setReason(HttpStatus.SC_EXPECTATION_FAILED,
+ "Expectation Failed");
+
+ // WebDAV Server-specific status codes
+ setReason(HttpStatus.SC_PROCESSING,
+ "Processing");
+ setReason(HttpStatus.SC_MULTI_STATUS,
+ "Multi-Status");
+ setReason(HttpStatus.SC_UNPROCESSABLE_ENTITY,
+ "Unprocessable Entity");
+ setReason(HttpStatus.SC_INSUFFICIENT_SPACE_ON_RESOURCE,
+ "Insufficient Space On Resource");
+ setReason(HttpStatus.SC_METHOD_FAILURE,
+ "Method Failure");
+ setReason(HttpStatus.SC_LOCKED,
+ "Locked");
+ setReason(HttpStatus.SC_INSUFFICIENT_STORAGE,
+ "Insufficient Storage");
+ setReason(HttpStatus.SC_FAILED_DEPENDENCY,
+ "Failed Dependency");
+ }
+
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/HttpConnectionMetricsImpl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/HttpConnectionMetricsImpl.java
new file mode 100644
index 000000000..bfc415082
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/HttpConnectionMetricsImpl.java
@@ -0,0 +1,148 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+
+/**
+ * Default implementation of the {@link HttpConnectionMetrics} interface.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpConnectionMetricsImpl implements HttpConnectionMetrics {
+
+ public static final String REQUEST_COUNT = "http.request-count";
+ public static final String RESPONSE_COUNT = "http.response-count";
+ public static final String SENT_BYTES_COUNT = "http.sent-bytes-count";
+ public static final String RECEIVED_BYTES_COUNT = "http.received-bytes-count";
+
+ private final HttpTransportMetrics inTransportMetric;
+ private final HttpTransportMetrics outTransportMetric;
+ private long requestCount = 0;
+ private long responseCount = 0;
+
+ /**
+ * The cache map for all metrics values.
+ */
+ private Map<String, Object> metricsCache;
+
+ public HttpConnectionMetricsImpl(
+ final HttpTransportMetrics inTransportMetric,
+ final HttpTransportMetrics outTransportMetric) {
+ super();
+ this.inTransportMetric = inTransportMetric;
+ this.outTransportMetric = outTransportMetric;
+ }
+
+ /* ------------------ Public interface method -------------------------- */
+
+ public long getReceivedBytesCount() {
+ if (this.inTransportMetric != null) {
+ return this.inTransportMetric.getBytesTransferred();
+ } else {
+ return -1;
+ }
+ }
+
+ public long getSentBytesCount() {
+ if (this.outTransportMetric != null) {
+ return this.outTransportMetric.getBytesTransferred();
+ } else {
+ return -1;
+ }
+ }
+
+ public long getRequestCount() {
+ return this.requestCount;
+ }
+
+ public void incrementRequestCount() {
+ this.requestCount++;
+ }
+
+ public long getResponseCount() {
+ return this.responseCount;
+ }
+
+ public void incrementResponseCount() {
+ this.responseCount++;
+ }
+
+ public Object getMetric(final String metricName) {
+ Object value = null;
+ if (this.metricsCache != null) {
+ value = this.metricsCache.get(metricName);
+ }
+ if (value == null) {
+ if (REQUEST_COUNT.equals(metricName)) {
+ value = Long.valueOf(requestCount);
+ } else if (RESPONSE_COUNT.equals(metricName)) {
+ value = Long.valueOf(responseCount);
+ } else if (RECEIVED_BYTES_COUNT.equals(metricName)) {
+ if (this.inTransportMetric != null) {
+ return Long.valueOf(this.inTransportMetric.getBytesTransferred());
+ } else {
+ return null;
+ }
+ } else if (SENT_BYTES_COUNT.equals(metricName)) {
+ if (this.outTransportMetric != null) {
+ return Long.valueOf(this.outTransportMetric.getBytesTransferred());
+ } else {
+ return null;
+ }
+ }
+ }
+ return value;
+ }
+
+ public void setMetric(final String metricName, final Object obj) {
+ if (this.metricsCache == null) {
+ this.metricsCache = new HashMap<String, Object>();
+ }
+ this.metricsCache.put(metricName, obj);
+ }
+
+ public void reset() {
+ if (this.outTransportMetric != null) {
+ this.outTransportMetric.reset();
+ }
+ if (this.inTransportMetric != null) {
+ this.inTransportMetric.reset();
+ }
+ this.requestCount = 0;
+ this.responseCount = 0;
+ this.metricsCache = null;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/NoConnectionReuseStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/NoConnectionReuseStrategy.java
new file mode 100644
index 000000000..fdf312844
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/NoConnectionReuseStrategy.java
@@ -0,0 +1,53 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * A strategy that never re-uses a connection.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class NoConnectionReuseStrategy implements ConnectionReuseStrategy {
+
+ public static final NoConnectionReuseStrategy INSTANCE = new NoConnectionReuseStrategy();
+
+ public NoConnectionReuseStrategy() {
+ super();
+ }
+
+ public boolean keepAlive(final HttpResponse response, final HttpContext context) {
+ return false;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpClientConnection.java
new file mode 100644
index 000000000..72f2f7e87
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpClientConnection.java
@@ -0,0 +1,283 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import ch.boye.httpclientandroidlib.HttpInetConnection;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.impl.io.SocketInputBuffer;
+import ch.boye.httpclientandroidlib.impl.io.SocketOutputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Implementation of a client-side HTTP connection that can be bound to an
+ * arbitrary {@link Socket} for receiving data from and transmitting data to
+ * a remote server.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultBHttpClientConnection}
+ */
+@NotThreadSafe
+@Deprecated
+public class SocketHttpClientConnection
+ extends AbstractHttpClientConnection implements HttpInetConnection {
+
+ private volatile boolean open;
+ private volatile Socket socket = null;
+
+ public SocketHttpClientConnection() {
+ super();
+ }
+
+ protected void assertNotOpen() {
+ Asserts.check(!this.open, "Connection is already open");
+ }
+
+ @Override
+ protected void assertOpen() {
+ Asserts.check(this.open, "Connection is not open");
+ }
+
+ /**
+ * Creates an instance of {@link SocketInputBuffer} to be used for
+ * receiving data from the given {@link Socket}.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a custom implementation of {@link SessionInputBuffer} interface.
+ *
+ * @see SocketInputBuffer#SocketInputBuffer(Socket, int, HttpParams)
+ *
+ * @param socket the socket.
+ * @param buffersize the buffer size.
+ * @param params HTTP parameters.
+ * @return session input buffer.
+ * @throws IOException in case of an I/O error.
+ */
+ protected SessionInputBuffer createSessionInputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ return new SocketInputBuffer(socket, buffersize, params);
+ }
+
+ /**
+ * Creates an instance of {@link SessionOutputBuffer} to be used for
+ * sending data to the given {@link Socket}.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a custom implementation of {@link SocketOutputBuffer} interface.
+ *
+ * @see SocketOutputBuffer#SocketOutputBuffer(Socket, int, HttpParams)
+ *
+ * @param socket the socket.
+ * @param buffersize the buffer size.
+ * @param params HTTP parameters.
+ * @return session output buffer.
+ * @throws IOException in case of an I/O error.
+ */
+ protected SessionOutputBuffer createSessionOutputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ return new SocketOutputBuffer(socket, buffersize, params);
+ }
+
+ /**
+ * Binds this connection to the given {@link Socket}. This socket will be
+ * used by the connection to send and receive data.
+ * <p>
+ * This method will invoke {@link #createSessionInputBuffer(Socket, int, HttpParams)}
+ * and {@link #createSessionOutputBuffer(Socket, int, HttpParams)} methods
+ * to create session input / output buffers bound to this socket and then
+ * will invoke {@link #init(SessionInputBuffer, SessionOutputBuffer, HttpParams)}
+ * method to pass references to those buffers to the underlying HTTP message
+ * parser and formatter.
+ * <p>
+ * After this method's execution the connection status will be reported
+ * as open and the {@link #isOpen()} will return <code>true</code>.
+ *
+ * @param socket the socket.
+ * @param params HTTP parameters.
+ * @throws IOException in case of an I/O error.
+ */
+ protected void bind(
+ final Socket socket,
+ final HttpParams params) throws IOException {
+ Args.notNull(socket, "Socket");
+ Args.notNull(params, "HTTP parameters");
+ this.socket = socket;
+
+ final int buffersize = params.getIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, -1);
+ init(
+ createSessionInputBuffer(socket, buffersize, params),
+ createSessionOutputBuffer(socket, buffersize, params),
+ params);
+
+ this.open = true;
+ }
+
+ public boolean isOpen() {
+ return this.open;
+ }
+
+ protected Socket getSocket() {
+ return this.socket;
+ }
+
+ public InetAddress getLocalAddress() {
+ if (this.socket != null) {
+ return this.socket.getLocalAddress();
+ } else {
+ return null;
+ }
+ }
+
+ public int getLocalPort() {
+ if (this.socket != null) {
+ return this.socket.getLocalPort();
+ } else {
+ return -1;
+ }
+ }
+
+ public InetAddress getRemoteAddress() {
+ if (this.socket != null) {
+ return this.socket.getInetAddress();
+ } else {
+ return null;
+ }
+ }
+
+ public int getRemotePort() {
+ if (this.socket != null) {
+ return this.socket.getPort();
+ } else {
+ return -1;
+ }
+ }
+
+ public void setSocketTimeout(final int timeout) {
+ assertOpen();
+ if (this.socket != null) {
+ try {
+ this.socket.setSoTimeout(timeout);
+ } catch (final SocketException ignore) {
+ // It is not quite clear from the Sun's documentation if there are any
+ // other legitimate cases for a socket exception to be thrown when setting
+ // SO_TIMEOUT besides the socket being already closed
+ }
+ }
+ }
+
+ public int getSocketTimeout() {
+ if (this.socket != null) {
+ try {
+ return this.socket.getSoTimeout();
+ } catch (final SocketException ignore) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ }
+
+ public void shutdown() throws IOException {
+ this.open = false;
+ final Socket tmpsocket = this.socket;
+ if (tmpsocket != null) {
+ tmpsocket.close();
+ }
+ }
+
+ public void close() throws IOException {
+ if (!this.open) {
+ return;
+ }
+ this.open = false;
+ final Socket sock = this.socket;
+ try {
+ doFlush();
+ try {
+ try {
+ sock.shutdownOutput();
+ } catch (final IOException ignore) {
+ }
+ try {
+ sock.shutdownInput();
+ } catch (final IOException ignore) {
+ }
+ } catch (final UnsupportedOperationException ignore) {
+ // if one isn't supported, the other one isn't either
+ }
+ } finally {
+ sock.close();
+ }
+ }
+
+ private static void formatAddress(final StringBuilder buffer, final SocketAddress socketAddress) {
+ if (socketAddress instanceof InetSocketAddress) {
+ final InetSocketAddress addr = ((InetSocketAddress) socketAddress);
+ buffer.append(addr.getAddress() != null ? addr.getAddress().getHostAddress() :
+ addr.getAddress())
+ .append(':')
+ .append(addr.getPort());
+ } else {
+ buffer.append(socketAddress);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (this.socket != null) {
+ final StringBuilder buffer = new StringBuilder();
+ final SocketAddress remoteAddress = this.socket.getRemoteSocketAddress();
+ final SocketAddress localAddress = this.socket.getLocalSocketAddress();
+ if (remoteAddress != null && localAddress != null) {
+ formatAddress(buffer, localAddress);
+ buffer.append("<->");
+ formatAddress(buffer, remoteAddress);
+ }
+ return buffer.toString();
+ } else {
+ return super.toString();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpServerConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpServerConnection.java
new file mode 100644
index 000000000..0a74b94a3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/SocketHttpServerConnection.java
@@ -0,0 +1,271 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import ch.boye.httpclientandroidlib.HttpInetConnection;
+import ch.boye.httpclientandroidlib.impl.io.SocketInputBuffer;
+import ch.boye.httpclientandroidlib.impl.io.SocketOutputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+@Deprecated
+public class SocketHttpServerConnection extends
+ AbstractHttpServerConnection implements HttpInetConnection {
+
+ private volatile boolean open;
+ private volatile Socket socket = null;
+
+ public SocketHttpServerConnection() {
+ super();
+ }
+
+ protected void assertNotOpen() {
+ Asserts.check(!this.open, "Connection is already open");
+ }
+
+ @Override
+ protected void assertOpen() {
+ Asserts.check(this.open, "Connection is not open");
+ }
+
+ /**
+ * Creates an instance of {@link SocketInputBuffer} to be used for
+ * receiving data from the given {@link Socket}.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a custom implementation of {@link SessionInputBuffer} interface.
+ *
+ * @see SocketInputBuffer#SocketInputBuffer(Socket, int, HttpParams)
+ *
+ * @param socket the socket.
+ * @param buffersize the buffer size.
+ * @param params HTTP parameters.
+ * @return session input buffer.
+ * @throws IOException in case of an I/O error.
+ */
+ protected SessionInputBuffer createSessionInputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ return new SocketInputBuffer(socket, buffersize, params);
+ }
+
+ /**
+ * Creates an instance of {@link SessionOutputBuffer} to be used for
+ * sending data to the given {@link Socket}.
+ * <p>
+ * This method can be overridden in a super class in order to provide
+ * a custom implementation of {@link SocketOutputBuffer} interface.
+ *
+ * @see SocketOutputBuffer#SocketOutputBuffer(Socket, int, HttpParams)
+ *
+ * @param socket the socket.
+ * @param buffersize the buffer size.
+ * @param params HTTP parameters.
+ * @return session output buffer.
+ * @throws IOException in case of an I/O error.
+ */
+ protected SessionOutputBuffer createSessionOutputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ return new SocketOutputBuffer(socket, buffersize, params);
+ }
+
+ /**
+ * Binds this connection to the given {@link Socket}. This socket will be
+ * used by the connection to send and receive data.
+ * <p>
+ * This method will invoke {@link #createSessionInputBuffer(Socket, int, HttpParams)}
+ * and {@link #createSessionOutputBuffer(Socket, int, HttpParams)} methods
+ * to create session input / output buffers bound to this socket and then
+ * will invoke {@link #init(SessionInputBuffer, SessionOutputBuffer, HttpParams)}
+ * method to pass references to those buffers to the underlying HTTP message
+ * parser and formatter.
+ * <p>
+ * After this method's execution the connection status will be reported
+ * as open and the {@link #isOpen()} will return <code>true</code>.
+ *
+ * @param socket the socket.
+ * @param params HTTP parameters.
+ * @throws IOException in case of an I/O error.
+ */
+ protected void bind(final Socket socket, final HttpParams params) throws IOException {
+ Args.notNull(socket, "Socket");
+ Args.notNull(params, "HTTP parameters");
+ this.socket = socket;
+
+ final int buffersize = params.getIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, -1);
+ init(
+ createSessionInputBuffer(socket, buffersize, params),
+ createSessionOutputBuffer(socket, buffersize, params),
+ params);
+
+ this.open = true;
+ }
+
+ protected Socket getSocket() {
+ return this.socket;
+ }
+
+ public boolean isOpen() {
+ return this.open;
+ }
+
+ public InetAddress getLocalAddress() {
+ if (this.socket != null) {
+ return this.socket.getLocalAddress();
+ } else {
+ return null;
+ }
+ }
+
+ public int getLocalPort() {
+ if (this.socket != null) {
+ return this.socket.getLocalPort();
+ } else {
+ return -1;
+ }
+ }
+
+ public InetAddress getRemoteAddress() {
+ if (this.socket != null) {
+ return this.socket.getInetAddress();
+ } else {
+ return null;
+ }
+ }
+
+ public int getRemotePort() {
+ if (this.socket != null) {
+ return this.socket.getPort();
+ } else {
+ return -1;
+ }
+ }
+
+ public void setSocketTimeout(final int timeout) {
+ assertOpen();
+ if (this.socket != null) {
+ try {
+ this.socket.setSoTimeout(timeout);
+ } catch (final SocketException ignore) {
+ // It is not quite clear from the Sun's documentation if there are any
+ // other legitimate cases for a socket exception to be thrown when setting
+ // SO_TIMEOUT besides the socket being already closed
+ }
+ }
+ }
+
+ public int getSocketTimeout() {
+ if (this.socket != null) {
+ try {
+ return this.socket.getSoTimeout();
+ } catch (final SocketException ignore) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ }
+
+ public void shutdown() throws IOException {
+ this.open = false;
+ final Socket tmpsocket = this.socket;
+ if (tmpsocket != null) {
+ tmpsocket.close();
+ }
+ }
+
+ public void close() throws IOException {
+ if (!this.open) {
+ return;
+ }
+ this.open = false;
+ this.open = false;
+ final Socket sock = this.socket;
+ try {
+ doFlush();
+ try {
+ try {
+ sock.shutdownOutput();
+ } catch (final IOException ignore) {
+ }
+ try {
+ sock.shutdownInput();
+ } catch (final IOException ignore) {
+ }
+ } catch (final UnsupportedOperationException ignore) {
+ // if one isn't supported, the other one isn't either
+ }
+ } finally {
+ sock.close();
+ }
+ }
+
+ private static void formatAddress(final StringBuilder buffer, final SocketAddress socketAddress) {
+ if (socketAddress instanceof InetSocketAddress) {
+ final InetSocketAddress addr = ((InetSocketAddress) socketAddress);
+ buffer.append(addr.getAddress() != null ? addr.getAddress().getHostAddress() :
+ addr.getAddress())
+ .append(':')
+ .append(addr.getPort());
+ } else {
+ buffer.append(socketAddress);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (this.socket != null) {
+ final StringBuilder buffer = new StringBuilder();
+ final SocketAddress remoteAddress = this.socket.getRemoteSocketAddress();
+ final SocketAddress localAddress = this.socket.getLocalSocketAddress();
+ if (remoteAddress != null && localAddress != null) {
+ formatAddress(buffer, localAddress);
+ buffer.append("<->");
+ formatAddress(buffer, remoteAddress);
+ }
+ return buffer.toString();
+ } else {
+ return super.toString();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/AuthSchemeBase.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/AuthSchemeBase.java
new file mode 100644
index 000000000..e1b98db9e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/AuthSchemeBase.java
@@ -0,0 +1,169 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.ChallengeState;
+import ch.boye.httpclientandroidlib.auth.ContextAwareAuthScheme;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract authentication scheme class that serves as a basis
+ * for all authentication schemes supported by HttpClient. This class
+ * defines the generic way of parsing an authentication challenge. It
+ * does not make any assumptions regarding the format of the challenge
+ * nor does it impose any specific way of responding to that challenge.
+ *
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public abstract class AuthSchemeBase implements ContextAwareAuthScheme {
+
+ private ChallengeState challengeState;
+
+ /**
+ * Creates an instance of <tt>AuthSchemeBase</tt> with the given challenge
+ * state.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public AuthSchemeBase(final ChallengeState challengeState) {
+ super();
+ this.challengeState = challengeState;
+ }
+
+ public AuthSchemeBase() {
+ super();
+ }
+
+ /**
+ * Processes the given challenge token. Some authentication schemes
+ * may involve multiple challenge-response exchanges. Such schemes must be able
+ * to maintain the state information when dealing with sequential challenges
+ *
+ * @param header the challenge header
+ *
+ * @throws MalformedChallengeException is thrown if the authentication challenge
+ * is malformed
+ */
+ public void processChallenge(final Header header) throws MalformedChallengeException {
+ Args.notNull(header, "Header");
+ final String authheader = header.getName();
+ if (authheader.equalsIgnoreCase(AUTH.WWW_AUTH)) {
+ this.challengeState = ChallengeState.TARGET;
+ } else if (authheader.equalsIgnoreCase(AUTH.PROXY_AUTH)) {
+ this.challengeState = ChallengeState.PROXY;
+ } else {
+ throw new MalformedChallengeException("Unexpected header name: " + authheader);
+ }
+
+ final CharArrayBuffer buffer;
+ int pos;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ pos = ((FormattedHeader) header).getValuePos();
+ } else {
+ final String s = header.getValue();
+ if (s == null) {
+ throw new MalformedChallengeException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ pos = 0;
+ }
+ while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ final int beginIndex = pos;
+ while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ final int endIndex = pos;
+ final String s = buffer.substring(beginIndex, endIndex);
+ if (!s.equalsIgnoreCase(getSchemeName())) {
+ throw new MalformedChallengeException("Invalid scheme identifier: " + s);
+ }
+
+ parseChallenge(buffer, pos, buffer.length());
+ }
+
+
+ @SuppressWarnings("deprecation")
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request,
+ final HttpContext context) throws AuthenticationException {
+ return authenticate(credentials, request);
+ }
+
+ protected abstract void parseChallenge(
+ CharArrayBuffer buffer, int beginIndex, int endIndex) throws MalformedChallengeException;
+
+ /**
+ * Returns <code>true</code> if authenticating against a proxy, <code>false</code>
+ * otherwise.
+ */
+ public boolean isProxy() {
+ return this.challengeState != null && this.challengeState == ChallengeState.PROXY;
+ }
+
+ /**
+ * Returns {@link ChallengeState} value or <code>null</code> if unchallenged.
+ *
+ * @since 4.2
+ */
+ public ChallengeState getChallengeState() {
+ return this.challengeState;
+ }
+
+ @Override
+ public String toString() {
+ final String name = getSchemeName();
+ if (name != null) {
+ return name.toUpperCase(Locale.ENGLISH);
+ } else {
+ return super.toString();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicScheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicScheme.java
new file mode 100644
index 000000000..c58b5e582
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicScheme.java
@@ -0,0 +1,219 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.nio.charset.Charset;
+
+import org.mozilla.apache.commons.codec.binary.Base64;
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.ChallengeState;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.message.BufferedHeader;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+import ch.boye.httpclientandroidlib.util.EncodingUtils;
+
+/**
+ * Basic authentication scheme as defined in RFC 2617.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicScheme extends RFC2617Scheme {
+
+/* Base64 instance removed by HttpClient for Android script. */
+ /** Whether the basic authentication process is complete */
+ private boolean complete;
+
+ /**
+ * @since 4.3
+ */
+ public BasicScheme(final Charset credentialsCharset) {
+ super(credentialsCharset);
+/* Base64 instance removed by HttpClient for Android script. */
+ this.complete = false;
+ }
+
+ /**
+ * Creates an instance of <tt>BasicScheme</tt> with the given challenge
+ * state.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public BasicScheme(final ChallengeState challengeState) {
+ super(challengeState);
+/* Base64 instance removed by HttpClient for Android script. */
+ }
+
+ public BasicScheme() {
+ this(Consts.ASCII);
+ }
+
+ /**
+ * Returns textual designation of the basic authentication scheme.
+ *
+ * @return <code>basic</code>
+ */
+ public String getSchemeName() {
+ return "basic";
+ }
+
+ /**
+ * Processes the Basic challenge.
+ *
+ * @param header the challenge header
+ *
+ * @throws MalformedChallengeException is thrown if the authentication challenge
+ * is malformed
+ */
+ @Override
+ public void processChallenge(
+ final Header header) throws MalformedChallengeException {
+ super.processChallenge(header);
+ this.complete = true;
+ }
+
+ /**
+ * Tests if the Basic authentication process has been completed.
+ *
+ * @return <tt>true</tt> if Basic authorization has been processed,
+ * <tt>false</tt> otherwise.
+ */
+ public boolean isComplete() {
+ return this.complete;
+ }
+
+ /**
+ * Returns <tt>false</tt>. Basic authentication scheme is request based.
+ *
+ * @return <tt>false</tt>.
+ */
+ public boolean isConnectionBased() {
+ return false;
+ }
+
+ /**
+ * @deprecated (4.2) Use {@link ch.boye.httpclientandroidlib.auth.ContextAwareAuthScheme#authenticate(
+ * Credentials, HttpRequest, ch.boye.httpclientandroidlib.protocol.HttpContext)}
+ */
+ @Deprecated
+ public Header authenticate(
+ final Credentials credentials, final HttpRequest request) throws AuthenticationException {
+ return authenticate(credentials, request, new BasicHttpContext());
+ }
+
+ /**
+ * Produces basic authorization header for the given set of {@link Credentials}.
+ *
+ * @param credentials The set of credentials to be used for authentication
+ * @param request The request being authenticated
+ * @throws ch.boye.httpclientandroidlib.auth.InvalidCredentialsException if authentication
+ * credentials are not valid or not applicable for this authentication scheme
+ * @throws AuthenticationException if authorization string cannot
+ * be generated due to an authentication failure
+ *
+ * @return a basic authorization string
+ */
+ @Override
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request,
+ final HttpContext context) throws AuthenticationException {
+
+ Args.notNull(credentials, "Credentials");
+ Args.notNull(request, "HTTP request");
+ final StringBuilder tmp = new StringBuilder();
+ tmp.append(credentials.getUserPrincipal().getName());
+ tmp.append(":");
+ tmp.append((credentials.getPassword() == null) ? "null" : credentials.getPassword());
+
+ final byte[] base64password = Base64.encodeBase64(
+ EncodingUtils.getBytes(tmp.toString(), getCredentialsCharset(request)));
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(32);
+ if (isProxy()) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": Basic ");
+ buffer.append(base64password, 0, base64password.length);
+
+ return new BufferedHeader(buffer);
+ }
+
+ /**
+ * Returns a basic <tt>Authorization</tt> header value for the given
+ * {@link Credentials} and charset.
+ *
+ * @param credentials The credentials to encode.
+ * @param charset The charset to use for encoding the credentials
+ *
+ * @return a basic authorization header
+ *
+ * @deprecated (4.3) use {@link #authenticate(Credentials, HttpRequest, HttpContext)}.
+ */
+ @Deprecated
+ public static Header authenticate(
+ final Credentials credentials,
+ final String charset,
+ final boolean proxy) {
+ Args.notNull(credentials, "Credentials");
+ Args.notNull(charset, "charset");
+
+ final StringBuilder tmp = new StringBuilder();
+ tmp.append(credentials.getUserPrincipal().getName());
+ tmp.append(":");
+ tmp.append((credentials.getPassword() == null) ? "null" : credentials.getPassword());
+
+ final byte[] base64password = Base64.encodeBase64(
+ EncodingUtils.getBytes(tmp.toString(), charset));
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(32);
+ if (proxy) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": Basic ");
+ buffer.append(base64password, 0, base64password.length);
+
+ return new BufferedHeader(buffer);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicSchemeFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicSchemeFactory.java
new file mode 100644
index 000000000..c4eb8c6be
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/BasicSchemeFactory.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.nio.charset.Charset;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeFactory;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link AuthSchemeProvider} implementation that creates and initializes
+ * {@link BasicScheme} instances.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class BasicSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider {
+
+ private final Charset charset;
+
+ /**
+ * @since 4.3
+ */
+ public BasicSchemeFactory(final Charset charset) {
+ super();
+ this.charset = charset;
+ }
+
+ public BasicSchemeFactory() {
+ this(null);
+ }
+
+ public AuthScheme newInstance(final HttpParams params) {
+ return new BasicScheme();
+ }
+
+ public AuthScheme create(final HttpContext context) {
+ return new BasicScheme(this.charset);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestScheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestScheme.java
new file mode 100644
index 000000000..542f6236b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestScheme.java
@@ -0,0 +1,489 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.ChallengeState;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.message.BasicHeaderValueFormatter;
+import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
+import ch.boye.httpclientandroidlib.message.BufferedHeader;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+import ch.boye.httpclientandroidlib.util.EncodingUtils;
+
+/**
+ * Digest authentication scheme as defined in RFC 2617.
+ * Both MD5 (default) and MD5-sess are supported.
+ * Currently only qop=auth or no qop is supported. qop=auth-int
+ * is unsupported. If auth and auth-int are provided, auth is
+ * used.
+ * <p/>
+ * Since the digest username is included as clear text in the generated
+ * Authentication header, the charset of the username must be compatible
+ * with the HTTP element charset used by the connection.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class DigestScheme extends RFC2617Scheme {
+
+ /**
+ * Hexa values used when creating 32 character long digest in HTTP DigestScheme
+ * in case of authentication.
+ *
+ * @see #encode(byte[])
+ */
+ private static final char[] HEXADECIMAL = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
+ 'e', 'f'
+ };
+
+ /** Whether the digest authentication process is complete */
+ private boolean complete;
+
+ private static final int QOP_UNKNOWN = -1;
+ private static final int QOP_MISSING = 0;
+ private static final int QOP_AUTH_INT = 1;
+ private static final int QOP_AUTH = 2;
+
+ private String lastNonce;
+ private long nounceCount;
+ private String cnonce;
+ private String a1;
+ private String a2;
+
+ /**
+ * @since 4.3
+ */
+ public DigestScheme(final Charset credentialsCharset) {
+ super(credentialsCharset);
+ this.complete = false;
+ }
+
+ /**
+ * Creates an instance of <tt>DigestScheme</tt> with the given challenge
+ * state.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public DigestScheme(final ChallengeState challengeState) {
+ super(challengeState);
+ }
+
+ public DigestScheme() {
+ this(Consts.ASCII);
+ }
+
+ /**
+ * Processes the Digest challenge.
+ *
+ * @param header the challenge header
+ *
+ * @throws MalformedChallengeException is thrown if the authentication challenge
+ * is malformed
+ */
+ @Override
+ public void processChallenge(
+ final Header header) throws MalformedChallengeException {
+ super.processChallenge(header);
+ this.complete = true;
+ }
+
+ /**
+ * Tests if the Digest authentication process has been completed.
+ *
+ * @return <tt>true</tt> if Digest authorization has been processed,
+ * <tt>false</tt> otherwise.
+ */
+ public boolean isComplete() {
+ final String s = getParameter("stale");
+ if ("true".equalsIgnoreCase(s)) {
+ return false;
+ } else {
+ return this.complete;
+ }
+ }
+
+ /**
+ * Returns textual designation of the digest authentication scheme.
+ *
+ * @return <code>digest</code>
+ */
+ public String getSchemeName() {
+ return "digest";
+ }
+
+ /**
+ * Returns <tt>false</tt>. Digest authentication scheme is request based.
+ *
+ * @return <tt>false</tt>.
+ */
+ public boolean isConnectionBased() {
+ return false;
+ }
+
+ public void overrideParamter(final String name, final String value) {
+ getParameters().put(name, value);
+ }
+
+ /**
+ * @deprecated (4.2) Use {@link ch.boye.httpclientandroidlib.auth.ContextAwareAuthScheme#authenticate(
+ * Credentials, HttpRequest, ch.boye.httpclientandroidlib.protocol.HttpContext)}
+ */
+ @Deprecated
+ public Header authenticate(
+ final Credentials credentials, final HttpRequest request) throws AuthenticationException {
+ return authenticate(credentials, request, new BasicHttpContext());
+ }
+
+ /**
+ * Produces a digest authorization string for the given set of
+ * {@link Credentials}, method name and URI.
+ *
+ * @param credentials A set of credentials to be used for athentication
+ * @param request The request being authenticated
+ *
+ * @throws ch.boye.httpclientandroidlib.auth.InvalidCredentialsException if authentication credentials
+ * are not valid or not applicable for this authentication scheme
+ * @throws AuthenticationException if authorization string cannot
+ * be generated due to an authentication failure
+ *
+ * @return a digest authorization string
+ */
+ @Override
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request,
+ final HttpContext context) throws AuthenticationException {
+
+ Args.notNull(credentials, "Credentials");
+ Args.notNull(request, "HTTP request");
+ if (getParameter("realm") == null) {
+ throw new AuthenticationException("missing realm in challenge");
+ }
+ if (getParameter("nonce") == null) {
+ throw new AuthenticationException("missing nonce in challenge");
+ }
+ // Add method name and request-URI to the parameter map
+ getParameters().put("methodname", request.getRequestLine().getMethod());
+ getParameters().put("uri", request.getRequestLine().getUri());
+ final String charset = getParameter("charset");
+ if (charset == null) {
+ getParameters().put("charset", getCredentialsCharset(request));
+ }
+ return createDigestHeader(credentials, request);
+ }
+
+ private static MessageDigest createMessageDigest(
+ final String digAlg) throws UnsupportedDigestAlgorithmException {
+ try {
+ return MessageDigest.getInstance(digAlg);
+ } catch (final Exception e) {
+ throw new UnsupportedDigestAlgorithmException(
+ "Unsupported algorithm in HTTP Digest authentication: "
+ + digAlg);
+ }
+ }
+
+ /**
+ * Creates digest-response header as defined in RFC2617.
+ *
+ * @param credentials User credentials
+ *
+ * @return The digest-response as String.
+ */
+ private Header createDigestHeader(
+ final Credentials credentials,
+ final HttpRequest request) throws AuthenticationException {
+ final String uri = getParameter("uri");
+ final String realm = getParameter("realm");
+ final String nonce = getParameter("nonce");
+ final String opaque = getParameter("opaque");
+ final String method = getParameter("methodname");
+ String algorithm = getParameter("algorithm");
+ // If an algorithm is not specified, default to MD5.
+ if (algorithm == null) {
+ algorithm = "MD5";
+ }
+
+ final Set<String> qopset = new HashSet<String>(8);
+ int qop = QOP_UNKNOWN;
+ final String qoplist = getParameter("qop");
+ if (qoplist != null) {
+ final StringTokenizer tok = new StringTokenizer(qoplist, ",");
+ while (tok.hasMoreTokens()) {
+ final String variant = tok.nextToken().trim();
+ qopset.add(variant.toLowerCase(Locale.ENGLISH));
+ }
+ if (request instanceof HttpEntityEnclosingRequest && qopset.contains("auth-int")) {
+ qop = QOP_AUTH_INT;
+ } else if (qopset.contains("auth")) {
+ qop = QOP_AUTH;
+ }
+ } else {
+ qop = QOP_MISSING;
+ }
+
+ if (qop == QOP_UNKNOWN) {
+ throw new AuthenticationException("None of the qop methods is supported: " + qoplist);
+ }
+
+ String charset = getParameter("charset");
+ if (charset == null) {
+ charset = "ISO-8859-1";
+ }
+
+ String digAlg = algorithm;
+ if (digAlg.equalsIgnoreCase("MD5-sess")) {
+ digAlg = "MD5";
+ }
+
+ final MessageDigest digester;
+ try {
+ digester = createMessageDigest(digAlg);
+ } catch (final UnsupportedDigestAlgorithmException ex) {
+ throw new AuthenticationException("Unsuppported digest algorithm: " + digAlg);
+ }
+
+ final String uname = credentials.getUserPrincipal().getName();
+ final String pwd = credentials.getPassword();
+
+ if (nonce.equals(this.lastNonce)) {
+ nounceCount++;
+ } else {
+ nounceCount = 1;
+ cnonce = null;
+ lastNonce = nonce;
+ }
+ final StringBuilder sb = new StringBuilder(256);
+ final Formatter formatter = new Formatter(sb, Locale.US);
+ formatter.format("%08x", nounceCount);
+ formatter.close();
+ final String nc = sb.toString();
+
+ if (cnonce == null) {
+ cnonce = createCnonce();
+ }
+
+ a1 = null;
+ a2 = null;
+ // 3.2.2.2: Calculating digest
+ if (algorithm.equalsIgnoreCase("MD5-sess")) {
+ // H( unq(username-value) ":" unq(realm-value) ":" passwd )
+ // ":" unq(nonce-value)
+ // ":" unq(cnonce-value)
+
+ // calculated one per session
+ sb.setLength(0);
+ sb.append(uname).append(':').append(realm).append(':').append(pwd);
+ final String checksum = encode(digester.digest(EncodingUtils.getBytes(sb.toString(), charset)));
+ sb.setLength(0);
+ sb.append(checksum).append(':').append(nonce).append(':').append(cnonce);
+ a1 = sb.toString();
+ } else {
+ // unq(username-value) ":" unq(realm-value) ":" passwd
+ sb.setLength(0);
+ sb.append(uname).append(':').append(realm).append(':').append(pwd);
+ a1 = sb.toString();
+ }
+
+ final String hasha1 = encode(digester.digest(EncodingUtils.getBytes(a1, charset)));
+
+ if (qop == QOP_AUTH) {
+ // Method ":" digest-uri-value
+ a2 = method + ':' + uri;
+ } else if (qop == QOP_AUTH_INT) {
+ // Method ":" digest-uri-value ":" H(entity-body)
+ HttpEntity entity = null;
+ if (request instanceof HttpEntityEnclosingRequest) {
+ entity = ((HttpEntityEnclosingRequest) request).getEntity();
+ }
+ if (entity != null && !entity.isRepeatable()) {
+ // If the entity is not repeatable, try falling back onto QOP_AUTH
+ if (qopset.contains("auth")) {
+ qop = QOP_AUTH;
+ a2 = method + ':' + uri;
+ } else {
+ throw new AuthenticationException("Qop auth-int cannot be used with " +
+ "a non-repeatable entity");
+ }
+ } else {
+ final HttpEntityDigester entityDigester = new HttpEntityDigester(digester);
+ try {
+ if (entity != null) {
+ entity.writeTo(entityDigester);
+ }
+ entityDigester.close();
+ } catch (final IOException ex) {
+ throw new AuthenticationException("I/O error reading entity content", ex);
+ }
+ a2 = method + ':' + uri + ':' + encode(entityDigester.getDigest());
+ }
+ } else {
+ a2 = method + ':' + uri;
+ }
+
+ final String hasha2 = encode(digester.digest(EncodingUtils.getBytes(a2, charset)));
+
+ // 3.2.2.1
+
+ final String digestValue;
+ if (qop == QOP_MISSING) {
+ sb.setLength(0);
+ sb.append(hasha1).append(':').append(nonce).append(':').append(hasha2);
+ digestValue = sb.toString();
+ } else {
+ sb.setLength(0);
+ sb.append(hasha1).append(':').append(nonce).append(':').append(nc).append(':')
+ .append(cnonce).append(':').append(qop == QOP_AUTH_INT ? "auth-int" : "auth")
+ .append(':').append(hasha2);
+ digestValue = sb.toString();
+ }
+
+ final String digest = encode(digester.digest(EncodingUtils.getAsciiBytes(digestValue)));
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(128);
+ if (isProxy()) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": Digest ");
+
+ final List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>(20);
+ params.add(new BasicNameValuePair("username", uname));
+ params.add(new BasicNameValuePair("realm", realm));
+ params.add(new BasicNameValuePair("nonce", nonce));
+ params.add(new BasicNameValuePair("uri", uri));
+ params.add(new BasicNameValuePair("response", digest));
+
+ if (qop != QOP_MISSING) {
+ params.add(new BasicNameValuePair("qop", qop == QOP_AUTH_INT ? "auth-int" : "auth"));
+ params.add(new BasicNameValuePair("nc", nc));
+ params.add(new BasicNameValuePair("cnonce", cnonce));
+ }
+ // algorithm cannot be null here
+ params.add(new BasicNameValuePair("algorithm", algorithm));
+ if (opaque != null) {
+ params.add(new BasicNameValuePair("opaque", opaque));
+ }
+
+ for (int i = 0; i < params.size(); i++) {
+ final BasicNameValuePair param = params.get(i);
+ if (i > 0) {
+ buffer.append(", ");
+ }
+ final String name = param.getName();
+ final boolean noQuotes = ("nc".equals(name) || "qop".equals(name)
+ || "algorithm".equals(name));
+ BasicHeaderValueFormatter.INSTANCE.formatNameValuePair(buffer, param, !noQuotes);
+ }
+ return new BufferedHeader(buffer);
+ }
+
+ String getCnonce() {
+ return cnonce;
+ }
+
+ String getA1() {
+ return a1;
+ }
+
+ String getA2() {
+ return a2;
+ }
+
+ /**
+ * Encodes the 128 bit (16 bytes) MD5 digest into a 32 characters long
+ * <CODE>String</CODE> according to RFC 2617.
+ *
+ * @param binaryData array containing the digest
+ * @return encoded MD5, or <CODE>null</CODE> if encoding failed
+ */
+ static String encode(final byte[] binaryData) {
+ final int n = binaryData.length;
+ final char[] buffer = new char[n * 2];
+ for (int i = 0; i < n; i++) {
+ final int low = (binaryData[i] & 0x0f);
+ final int high = ((binaryData[i] & 0xf0) >> 4);
+ buffer[i * 2] = HEXADECIMAL[high];
+ buffer[(i * 2) + 1] = HEXADECIMAL[low];
+ }
+
+ return new String(buffer);
+ }
+
+
+ /**
+ * Creates a random cnonce value based on the current time.
+ *
+ * @return The cnonce value as String.
+ */
+ public static String createCnonce() {
+ final SecureRandom rnd = new SecureRandom();
+ final byte[] tmp = new byte[8];
+ rnd.nextBytes(tmp);
+ return encode(tmp);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("DIGEST [complete=").append(complete)
+ .append(", nonce=").append(lastNonce)
+ .append(", nc=").append(nounceCount)
+ .append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestSchemeFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestSchemeFactory.java
new file mode 100644
index 000000000..0582bed49
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/DigestSchemeFactory.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.nio.charset.Charset;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeFactory;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link AuthSchemeProvider} implementation that creates and initializes
+ * {@link DigestScheme} instances.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class DigestSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider {
+
+ private final Charset charset;
+
+ /**
+ * @since 4.3
+ */
+ public DigestSchemeFactory(final Charset charset) {
+ super();
+ this.charset = charset;
+ }
+
+ public DigestSchemeFactory() {
+ this(null);
+ }
+
+ public AuthScheme newInstance(final HttpParams params) {
+ return new DigestScheme();
+ }
+
+ public AuthScheme create(final HttpContext context) {
+ return new DigestScheme(this.charset);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpAuthenticator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpAuthenticator.java
new file mode 100644
index 000000000..28b8b74d0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpAuthenticator.java
@@ -0,0 +1,245 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Queue;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.auth.AuthOption;
+import ch.boye.httpclientandroidlib.auth.AuthProtocolState;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.ContextAwareAuthScheme;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * @since 4.3
+ */
+public class HttpAuthenticator {
+
+ public HttpClientAndroidLog log;
+
+ public HttpAuthenticator(final HttpClientAndroidLog log) {
+ super();
+ this.log = log != null ? log : new HttpClientAndroidLog(getClass());
+ }
+
+ public HttpAuthenticator() {
+ this(null);
+ }
+
+ public boolean isAuthenticationRequested(
+ final HttpHost host,
+ final HttpResponse response,
+ final AuthenticationStrategy authStrategy,
+ final AuthState authState,
+ final HttpContext context) {
+ if (authStrategy.isAuthenticationRequested(host, response, context)) {
+ this.log.debug("Authentication required");
+ if (authState.getState() == AuthProtocolState.SUCCESS) {
+ authStrategy.authFailed(host, authState.getAuthScheme(), context);
+ }
+ return true;
+ } else {
+ switch (authState.getState()) {
+ case CHALLENGED:
+ case HANDSHAKE:
+ this.log.debug("Authentication succeeded");
+ authState.setState(AuthProtocolState.SUCCESS);
+ authStrategy.authSucceeded(host, authState.getAuthScheme(), context);
+ break;
+ case SUCCESS:
+ break;
+ default:
+ authState.setState(AuthProtocolState.UNCHALLENGED);
+ }
+ return false;
+ }
+ }
+
+ public boolean handleAuthChallenge(
+ final HttpHost host,
+ final HttpResponse response,
+ final AuthenticationStrategy authStrategy,
+ final AuthState authState,
+ final HttpContext context) {
+ try {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(host.toHostString() + " requested authentication");
+ }
+ final Map<String, Header> challenges = authStrategy.getChallenges(host, response, context);
+ if (challenges.isEmpty()) {
+ this.log.debug("Response contains no authentication challenges");
+ return false;
+ }
+
+ final AuthScheme authScheme = authState.getAuthScheme();
+ switch (authState.getState()) {
+ case FAILURE:
+ return false;
+ case SUCCESS:
+ authState.reset();
+ break;
+ case CHALLENGED:
+ case HANDSHAKE:
+ if (authScheme == null) {
+ this.log.debug("Auth scheme is null");
+ authStrategy.authFailed(host, null, context);
+ authState.reset();
+ authState.setState(AuthProtocolState.FAILURE);
+ return false;
+ }
+ case UNCHALLENGED:
+ if (authScheme != null) {
+ final String id = authScheme.getSchemeName();
+ final Header challenge = challenges.get(id.toLowerCase(Locale.ENGLISH));
+ if (challenge != null) {
+ this.log.debug("Authorization challenge processed");
+ authScheme.processChallenge(challenge);
+ if (authScheme.isComplete()) {
+ this.log.debug("Authentication failed");
+ authStrategy.authFailed(host, authState.getAuthScheme(), context);
+ authState.reset();
+ authState.setState(AuthProtocolState.FAILURE);
+ return false;
+ } else {
+ authState.setState(AuthProtocolState.HANDSHAKE);
+ return true;
+ }
+ } else {
+ authState.reset();
+ // Retry authentication with a different scheme
+ }
+ }
+ }
+ final Queue<AuthOption> authOptions = authStrategy.select(challenges, host, response, context);
+ if (authOptions != null && !authOptions.isEmpty()) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Selected authentication options: " + authOptions);
+ }
+ authState.setState(AuthProtocolState.CHALLENGED);
+ authState.update(authOptions);
+ return true;
+ } else {
+ return false;
+ }
+ } catch (final MalformedChallengeException ex) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Malformed challenge: " + ex.getMessage());
+ }
+ authState.reset();
+ return false;
+ }
+ }
+
+ public void generateAuthResponse(
+ final HttpRequest request,
+ final AuthState authState,
+ final HttpContext context) throws HttpException, IOException {
+ AuthScheme authScheme = authState.getAuthScheme();
+ Credentials creds = authState.getCredentials();
+ switch (authState.getState()) {
+ case FAILURE:
+ return;
+ case SUCCESS:
+ ensureAuthScheme(authScheme);
+ if (authScheme.isConnectionBased()) {
+ return;
+ }
+ break;
+ case CHALLENGED:
+ final Queue<AuthOption> authOptions = authState.getAuthOptions();
+ if (authOptions != null) {
+ while (!authOptions.isEmpty()) {
+ final AuthOption authOption = authOptions.remove();
+ authScheme = authOption.getAuthScheme();
+ creds = authOption.getCredentials();
+ authState.update(authScheme, creds);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Generating response to an authentication challenge using "
+ + authScheme.getSchemeName() + " scheme");
+ }
+ try {
+ final Header header = doAuth(authScheme, creds, request, context);
+ request.addHeader(header);
+ break;
+ } catch (final AuthenticationException ex) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn(authScheme + " authentication error: " + ex.getMessage());
+ }
+ }
+ }
+ return;
+ } else {
+ ensureAuthScheme(authScheme);
+ }
+ }
+ if (authScheme != null) {
+ try {
+ final Header header = doAuth(authScheme, creds, request, context);
+ request.addHeader(header);
+ } catch (final AuthenticationException ex) {
+ if (this.log.isErrorEnabled()) {
+ this.log.error(authScheme + " authentication error: " + ex.getMessage());
+ }
+ }
+ }
+ }
+
+ private void ensureAuthScheme(final AuthScheme authScheme) {
+ Asserts.notNull(authScheme, "Auth scheme");
+ }
+
+ @SuppressWarnings("deprecation")
+ private Header doAuth(
+ final AuthScheme authScheme,
+ final Credentials creds,
+ final HttpRequest request,
+ final HttpContext context) throws AuthenticationException {
+ if (authScheme instanceof ContextAwareAuthScheme) {
+ return ((ContextAwareAuthScheme) authScheme).authenticate(creds, request, context);
+ } else {
+ return authScheme.authenticate(creds, request);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpEntityDigester.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpEntityDigester.java
new file mode 100644
index 000000000..053951587
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/HttpEntityDigester.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+
+class HttpEntityDigester extends OutputStream {
+
+ private final MessageDigest digester;
+ private boolean closed;
+ private byte[] digest;
+
+ HttpEntityDigester(final MessageDigest digester) {
+ super();
+ this.digester = digester;
+ this.digester.reset();
+ }
+
+ @Override
+ public void write(final int b) throws IOException {
+ if (this.closed) {
+ throw new IOException("Stream has been already closed");
+ }
+ this.digester.update((byte) b);
+ }
+
+ @Override
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ if (this.closed) {
+ throw new IOException("Stream has been already closed");
+ }
+ this.digester.update(b, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (this.closed) {
+ return;
+ }
+ this.closed = true;
+ this.digest = this.digester.digest();
+ super.close();
+ }
+
+ public byte[] getDigest() {
+ return this.digest;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngine.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngine.java
new file mode 100644
index 000000000..ce2457000
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngine.java
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+/**
+ * Abstract NTLM authentication engine. The engine can be used to
+ * generate Type1 messages and Type3 messages in response to a
+ * Type2 challenge.
+ *
+ * @since 4.0
+ */
+public interface NTLMEngine {
+
+ /**
+ * Generates a Type1 message given the domain and workstation.
+ *
+ * @param domain Optional Windows domain name. Can be <code>null</code>.
+ * @param workstation Optional Windows workstation name. Can be
+ * <code>null</code>.
+ * @return Type1 message
+ * @throws NTLMEngineException
+ */
+ String generateType1Msg(
+ String domain,
+ String workstation) throws NTLMEngineException;
+
+ /**
+ * Generates a Type3 message given the user credentials and the
+ * authentication challenge.
+ *
+ * @param username Windows user name
+ * @param password Password
+ * @param domain Windows domain name
+ * @param workstation Windows workstation name
+ * @param challenge Type2 challenge.
+ * @return Type3 response.
+ * @throws NTLMEngineException
+ */
+ String generateType3Msg(
+ String username,
+ String password,
+ String domain,
+ String workstation,
+ String challenge) throws NTLMEngineException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineException.java
new file mode 100644
index 000000000..88ef96912
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineException.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+
+/**
+ * Signals NTLM protocol failure.
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class NTLMEngineException extends AuthenticationException {
+
+ private static final long serialVersionUID = 6027981323731768824L;
+
+ public NTLMEngineException() {
+ super();
+ }
+
+ /**
+ * Creates a new NTLMEngineException with the specified message.
+ *
+ * @param message the exception detail message
+ */
+ public NTLMEngineException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new NTLMEngineException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public NTLMEngineException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineImpl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineImpl.java
new file mode 100644
index 000000000..195148f6b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMEngineImpl.java
@@ -0,0 +1,1672 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.io.UnsupportedEncodingException;
+import java.security.Key;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Locale;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.mozilla.apache.commons.codec.binary.Base64;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.EncodingUtils;
+
+/**
+ * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM
+ * authentication protocol.
+ *
+ * @since 4.1
+ */
+@NotThreadSafe
+final class NTLMEngineImpl implements NTLMEngine {
+
+ // Flags we use; descriptions according to:
+ // http://davenport.sourceforge.net/ntlm.html
+ // and
+ // http://msdn.microsoft.com/en-us/library/cc236650%28v=prot.20%29.aspx
+ protected static final int FLAG_REQUEST_UNICODE_ENCODING = 0x00000001; // Unicode string encoding requested
+ protected static final int FLAG_REQUEST_TARGET = 0x00000004; // Requests target field
+ protected static final int FLAG_REQUEST_SIGN = 0x00000010; // Requests all messages have a signature attached, in NEGOTIATE message.
+ protected static final int FLAG_REQUEST_SEAL = 0x00000020; // Request key exchange for message confidentiality in NEGOTIATE message. MUST be used in conjunction with 56BIT.
+ protected static final int FLAG_REQUEST_LAN_MANAGER_KEY = 0x00000080; // Request Lan Manager key instead of user session key
+ protected static final int FLAG_REQUEST_NTLMv1 = 0x00000200; // Request NTLMv1 security. MUST be set in NEGOTIATE and CHALLENGE both
+ protected static final int FLAG_DOMAIN_PRESENT = 0x00001000; // Domain is present in message
+ protected static final int FLAG_WORKSTATION_PRESENT = 0x00002000; // Workstation is present in message
+ protected static final int FLAG_REQUEST_ALWAYS_SIGN = 0x00008000; // Requests a signature block on all messages. Overridden by REQUEST_SIGN and REQUEST_SEAL.
+ protected static final int FLAG_REQUEST_NTLM2_SESSION = 0x00080000; // From server in challenge, requesting NTLM2 session security
+ protected static final int FLAG_REQUEST_VERSION = 0x02000000; // Request protocol version
+ protected static final int FLAG_TARGETINFO_PRESENT = 0x00800000; // From server in challenge message, indicating targetinfo is present
+ protected static final int FLAG_REQUEST_128BIT_KEY_EXCH = 0x20000000; // Request explicit 128-bit key exchange
+ protected static final int FLAG_REQUEST_EXPLICIT_KEY_EXCH = 0x40000000; // Request explicit key exchange
+ protected static final int FLAG_REQUEST_56BIT_ENCRYPTION = 0x80000000; // Must be used in conjunction with SEAL
+
+
+ /** Secure random generator */
+ private static final java.security.SecureRandom RND_GEN;
+ static {
+ java.security.SecureRandom rnd = null;
+ try {
+ rnd = java.security.SecureRandom.getInstance("SHA1PRNG");
+ } catch (final Exception ignore) {
+ }
+ RND_GEN = rnd;
+ }
+
+ /** Character encoding */
+ static final String DEFAULT_CHARSET = "ASCII";
+
+ /** The character set to use for encoding the credentials */
+ private String credentialCharset = DEFAULT_CHARSET;
+
+ /** The signature string as bytes in the default encoding */
+ private static final byte[] SIGNATURE;
+
+ static {
+ final byte[] bytesWithoutNull = EncodingUtils.getBytes("NTLMSSP", "ASCII");
+ SIGNATURE = new byte[bytesWithoutNull.length + 1];
+ System.arraycopy(bytesWithoutNull, 0, SIGNATURE, 0, bytesWithoutNull.length);
+ SIGNATURE[bytesWithoutNull.length] = (byte) 0x00;
+ }
+
+ /**
+ * Returns the response for the given message.
+ *
+ * @param message
+ * the message that was received from the server.
+ * @param username
+ * the username to authenticate with.
+ * @param password
+ * the password to authenticate with.
+ * @param host
+ * The host.
+ * @param domain
+ * the NT domain to authenticate in.
+ * @return The response.
+ * @throws ch.boye.httpclientandroidlib.HttpException
+ * If the messages cannot be retrieved.
+ */
+ final String getResponseFor(final String message, final String username, final String password,
+ final String host, final String domain) throws NTLMEngineException {
+
+ final String response;
+ if (message == null || message.trim().equals("")) {
+ response = getType1Message(host, domain);
+ } else {
+ final Type2Message t2m = new Type2Message(message);
+ response = getType3Message(username, password, host, domain, t2m.getChallenge(), t2m
+ .getFlags(), t2m.getTarget(), t2m.getTargetInfo());
+ }
+ return response;
+ }
+
+ /**
+ * Creates the first message (type 1 message) in the NTLM authentication
+ * sequence. This message includes the user name, domain and host for the
+ * authentication session.
+ *
+ * @param host
+ * the computer name of the host requesting authentication.
+ * @param domain
+ * The domain to authenticate with.
+ * @return String the message to add to the HTTP request header.
+ */
+ String getType1Message(final String host, final String domain) throws NTLMEngineException {
+ return new Type1Message(domain, host).getResponse();
+ }
+
+ /**
+ * Creates the type 3 message using the given server nonce. The type 3
+ * message includes all the information for authentication, host, domain,
+ * username and the result of encrypting the nonce sent by the server using
+ * the user's password as the key.
+ *
+ * @param user
+ * The user name. This should not include the domain name.
+ * @param password
+ * The password.
+ * @param host
+ * The host that is originating the authentication request.
+ * @param domain
+ * The domain to authenticate within.
+ * @param nonce
+ * the 8 byte array the server sent.
+ * @return The type 3 message.
+ * @throws NTLMEngineException
+ * If {@link #RC4(byte[],byte[])} fails.
+ */
+ String getType3Message(final String user, final String password, final String host, final String domain,
+ final byte[] nonce, final int type2Flags, final String target, final byte[] targetInformation)
+ throws NTLMEngineException {
+ return new Type3Message(domain, host, user, password, nonce, type2Flags, target,
+ targetInformation).getResponse();
+ }
+
+ /**
+ * @return Returns the credentialCharset.
+ */
+ String getCredentialCharset() {
+ return credentialCharset;
+ }
+
+ /**
+ * @param credentialCharset
+ * The credentialCharset to set.
+ */
+ void setCredentialCharset(final String credentialCharset) {
+ this.credentialCharset = credentialCharset;
+ }
+
+ /** Strip dot suffix from a name */
+ private static String stripDotSuffix(final String value) {
+ if (value == null) {
+ return null;
+ }
+ final int index = value.indexOf(".");
+ if (index != -1) {
+ return value.substring(0, index);
+ }
+ return value;
+ }
+
+ /** Convert host to standard form */
+ private static String convertHost(final String host) {
+ return stripDotSuffix(host);
+ }
+
+ /** Convert domain to standard form */
+ private static String convertDomain(final String domain) {
+ return stripDotSuffix(domain);
+ }
+
+ private static int readULong(final byte[] src, final int index) throws NTLMEngineException {
+ if (src.length < index + 4) {
+ throw new NTLMEngineException("NTLM authentication - buffer too small for DWORD");
+ }
+ return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8)
+ | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24);
+ }
+
+ private static int readUShort(final byte[] src, final int index) throws NTLMEngineException {
+ if (src.length < index + 2) {
+ throw new NTLMEngineException("NTLM authentication - buffer too small for WORD");
+ }
+ return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8);
+ }
+
+ private static byte[] readSecurityBuffer(final byte[] src, final int index) throws NTLMEngineException {
+ final int length = readUShort(src, index);
+ final int offset = readULong(src, index + 4);
+ if (src.length < offset + length) {
+ throw new NTLMEngineException(
+ "NTLM authentication - buffer too small for data item");
+ }
+ final byte[] buffer = new byte[length];
+ System.arraycopy(src, offset, buffer, 0, length);
+ return buffer;
+ }
+
+ /** Calculate a challenge block */
+ private static byte[] makeRandomChallenge() throws NTLMEngineException {
+ if (RND_GEN == null) {
+ throw new NTLMEngineException("Random generator not available");
+ }
+ final byte[] rval = new byte[8];
+ synchronized (RND_GEN) {
+ RND_GEN.nextBytes(rval);
+ }
+ return rval;
+ }
+
+ /** Calculate a 16-byte secondary key */
+ private static byte[] makeSecondaryKey() throws NTLMEngineException {
+ if (RND_GEN == null) {
+ throw new NTLMEngineException("Random generator not available");
+ }
+ final byte[] rval = new byte[16];
+ synchronized (RND_GEN) {
+ RND_GEN.nextBytes(rval);
+ }
+ return rval;
+ }
+
+ protected static class CipherGen {
+
+ protected final String domain;
+ protected final String user;
+ protected final String password;
+ protected final byte[] challenge;
+ protected final String target;
+ protected final byte[] targetInformation;
+
+ // Information we can generate but may be passed in (for testing)
+ protected byte[] clientChallenge;
+ protected byte[] clientChallenge2;
+ protected byte[] secondaryKey;
+ protected byte[] timestamp;
+
+ // Stuff we always generate
+ protected byte[] lmHash = null;
+ protected byte[] lmResponse = null;
+ protected byte[] ntlmHash = null;
+ protected byte[] ntlmResponse = null;
+ protected byte[] ntlmv2Hash = null;
+ protected byte[] lmv2Hash = null;
+ protected byte[] lmv2Response = null;
+ protected byte[] ntlmv2Blob = null;
+ protected byte[] ntlmv2Response = null;
+ protected byte[] ntlm2SessionResponse = null;
+ protected byte[] lm2SessionResponse = null;
+ protected byte[] lmUserSessionKey = null;
+ protected byte[] ntlmUserSessionKey = null;
+ protected byte[] ntlmv2UserSessionKey = null;
+ protected byte[] ntlm2SessionResponseUserSessionKey = null;
+ protected byte[] lanManagerSessionKey = null;
+
+ public CipherGen(final String domain, final String user, final String password,
+ final byte[] challenge, final String target, final byte[] targetInformation,
+ final byte[] clientChallenge, final byte[] clientChallenge2,
+ final byte[] secondaryKey, final byte[] timestamp) {
+ this.domain = domain;
+ this.target = target;
+ this.user = user;
+ this.password = password;
+ this.challenge = challenge;
+ this.targetInformation = targetInformation;
+ this.clientChallenge = clientChallenge;
+ this.clientChallenge2 = clientChallenge2;
+ this.secondaryKey = secondaryKey;
+ this.timestamp = timestamp;
+ }
+
+ public CipherGen(final String domain, final String user, final String password,
+ final byte[] challenge, final String target, final byte[] targetInformation) {
+ this(domain, user, password, challenge, target, targetInformation, null, null, null, null);
+ }
+
+ /** Calculate and return client challenge */
+ public byte[] getClientChallenge()
+ throws NTLMEngineException {
+ if (clientChallenge == null) {
+ clientChallenge = makeRandomChallenge();
+ }
+ return clientChallenge;
+ }
+
+ /** Calculate and return second client challenge */
+ public byte[] getClientChallenge2()
+ throws NTLMEngineException {
+ if (clientChallenge2 == null) {
+ clientChallenge2 = makeRandomChallenge();
+ }
+ return clientChallenge2;
+ }
+
+ /** Calculate and return random secondary key */
+ public byte[] getSecondaryKey()
+ throws NTLMEngineException {
+ if (secondaryKey == null) {
+ secondaryKey = makeSecondaryKey();
+ }
+ return secondaryKey;
+ }
+
+ /** Calculate and return the LMHash */
+ public byte[] getLMHash()
+ throws NTLMEngineException {
+ if (lmHash == null) {
+ lmHash = lmHash(password);
+ }
+ return lmHash;
+ }
+
+ /** Calculate and return the LMResponse */
+ public byte[] getLMResponse()
+ throws NTLMEngineException {
+ if (lmResponse == null) {
+ lmResponse = lmResponse(getLMHash(),challenge);
+ }
+ return lmResponse;
+ }
+
+ /** Calculate and return the NTLMHash */
+ public byte[] getNTLMHash()
+ throws NTLMEngineException {
+ if (ntlmHash == null) {
+ ntlmHash = ntlmHash(password);
+ }
+ return ntlmHash;
+ }
+
+ /** Calculate and return the NTLMResponse */
+ public byte[] getNTLMResponse()
+ throws NTLMEngineException {
+ if (ntlmResponse == null) {
+ ntlmResponse = lmResponse(getNTLMHash(),challenge);
+ }
+ return ntlmResponse;
+ }
+
+ /** Calculate the LMv2 hash */
+ public byte[] getLMv2Hash()
+ throws NTLMEngineException {
+ if (lmv2Hash == null) {
+ lmv2Hash = lmv2Hash(domain, user, getNTLMHash());
+ }
+ return lmv2Hash;
+ }
+
+ /** Calculate the NTLMv2 hash */
+ public byte[] getNTLMv2Hash()
+ throws NTLMEngineException {
+ if (ntlmv2Hash == null) {
+ ntlmv2Hash = ntlmv2Hash(domain, user, getNTLMHash());
+ }
+ return ntlmv2Hash;
+ }
+
+ /** Calculate a timestamp */
+ public byte[] getTimestamp() {
+ if (timestamp == null) {
+ long time = System.currentTimeMillis();
+ time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch.
+ time *= 10000; // tenths of a microsecond.
+ // convert to little-endian byte array.
+ timestamp = new byte[8];
+ for (int i = 0; i < 8; i++) {
+ timestamp[i] = (byte) time;
+ time >>>= 8;
+ }
+ }
+ return timestamp;
+ }
+
+ /** Calculate the NTLMv2Blob */
+ public byte[] getNTLMv2Blob()
+ throws NTLMEngineException {
+ if (ntlmv2Blob == null) {
+ ntlmv2Blob = createBlob(getClientChallenge2(), targetInformation, getTimestamp());
+ }
+ return ntlmv2Blob;
+ }
+
+ /** Calculate the NTLMv2Response */
+ public byte[] getNTLMv2Response()
+ throws NTLMEngineException {
+ if (ntlmv2Response == null) {
+ ntlmv2Response = lmv2Response(getNTLMv2Hash(),challenge,getNTLMv2Blob());
+ }
+ return ntlmv2Response;
+ }
+
+ /** Calculate the LMv2Response */
+ public byte[] getLMv2Response()
+ throws NTLMEngineException {
+ if (lmv2Response == null) {
+ lmv2Response = lmv2Response(getLMv2Hash(),challenge,getClientChallenge());
+ }
+ return lmv2Response;
+ }
+
+ /** Get NTLM2SessionResponse */
+ public byte[] getNTLM2SessionResponse()
+ throws NTLMEngineException {
+ if (ntlm2SessionResponse == null) {
+ ntlm2SessionResponse = ntlm2SessionResponse(getNTLMHash(),challenge,getClientChallenge());
+ }
+ return ntlm2SessionResponse;
+ }
+
+ /** Calculate and return LM2 session response */
+ public byte[] getLM2SessionResponse()
+ throws NTLMEngineException {
+ if (lm2SessionResponse == null) {
+ final byte[] clChallenge = getClientChallenge();
+ lm2SessionResponse = new byte[24];
+ System.arraycopy(clChallenge, 0, lm2SessionResponse, 0, clChallenge.length);
+ Arrays.fill(lm2SessionResponse, clChallenge.length, lm2SessionResponse.length, (byte) 0x00);
+ }
+ return lm2SessionResponse;
+ }
+
+ /** Get LMUserSessionKey */
+ public byte[] getLMUserSessionKey()
+ throws NTLMEngineException {
+ if (lmUserSessionKey == null) {
+ lmUserSessionKey = new byte[16];
+ System.arraycopy(getLMHash(), 0, lmUserSessionKey, 0, 8);
+ Arrays.fill(lmUserSessionKey, 8, 16, (byte) 0x00);
+ }
+ return lmUserSessionKey;
+ }
+
+ /** Get NTLMUserSessionKey */
+ public byte[] getNTLMUserSessionKey()
+ throws NTLMEngineException {
+ if (ntlmUserSessionKey == null) {
+ final MD4 md4 = new MD4();
+ md4.update(getNTLMHash());
+ ntlmUserSessionKey = md4.getOutput();
+ }
+ return ntlmUserSessionKey;
+ }
+
+ /** GetNTLMv2UserSessionKey */
+ public byte[] getNTLMv2UserSessionKey()
+ throws NTLMEngineException {
+ if (ntlmv2UserSessionKey == null) {
+ final byte[] ntlmv2hash = getNTLMv2Hash();
+ final byte[] truncatedResponse = new byte[16];
+ System.arraycopy(getNTLMv2Response(), 0, truncatedResponse, 0, 16);
+ ntlmv2UserSessionKey = hmacMD5(truncatedResponse, ntlmv2hash);
+ }
+ return ntlmv2UserSessionKey;
+ }
+
+ /** Get NTLM2SessionResponseUserSessionKey */
+ public byte[] getNTLM2SessionResponseUserSessionKey()
+ throws NTLMEngineException {
+ if (ntlm2SessionResponseUserSessionKey == null) {
+ final byte[] ntlm2SessionResponseNonce = getLM2SessionResponse();
+ final byte[] sessionNonce = new byte[challenge.length + ntlm2SessionResponseNonce.length];
+ System.arraycopy(challenge, 0, sessionNonce, 0, challenge.length);
+ System.arraycopy(ntlm2SessionResponseNonce, 0, sessionNonce, challenge.length, ntlm2SessionResponseNonce.length);
+ ntlm2SessionResponseUserSessionKey = hmacMD5(sessionNonce,getNTLMUserSessionKey());
+ }
+ return ntlm2SessionResponseUserSessionKey;
+ }
+
+ /** Get LAN Manager session key */
+ public byte[] getLanManagerSessionKey()
+ throws NTLMEngineException {
+ if (lanManagerSessionKey == null) {
+ try {
+ final byte[] keyBytes = new byte[14];
+ System.arraycopy(getLMHash(), 0, keyBytes, 0, 8);
+ Arrays.fill(keyBytes, 8, keyBytes.length, (byte)0xbd);
+ final Key lowKey = createDESKey(keyBytes, 0);
+ final Key highKey = createDESKey(keyBytes, 7);
+ final byte[] truncatedResponse = new byte[8];
+ System.arraycopy(getLMResponse(), 0, truncatedResponse, 0, truncatedResponse.length);
+ Cipher des = Cipher.getInstance("DES/ECB/NoPadding");
+ des.init(Cipher.ENCRYPT_MODE, lowKey);
+ final byte[] lowPart = des.doFinal(truncatedResponse);
+ des = Cipher.getInstance("DES/ECB/NoPadding");
+ des.init(Cipher.ENCRYPT_MODE, highKey);
+ final byte[] highPart = des.doFinal(truncatedResponse);
+ lanManagerSessionKey = new byte[16];
+ System.arraycopy(lowPart, 0, lanManagerSessionKey, 0, lowPart.length);
+ System.arraycopy(highPart, 0, lanManagerSessionKey, lowPart.length, highPart.length);
+ } catch (final Exception e) {
+ throw new NTLMEngineException(e.getMessage(), e);
+ }
+ }
+ return lanManagerSessionKey;
+ }
+ }
+
+ /** Calculates HMAC-MD5 */
+ static byte[] hmacMD5(final byte[] value, final byte[] key)
+ throws NTLMEngineException {
+ final HMACMD5 hmacMD5 = new HMACMD5(key);
+ hmacMD5.update(value);
+ return hmacMD5.getOutput();
+ }
+
+ /** Calculates RC4 */
+ static byte[] RC4(final byte[] value, final byte[] key)
+ throws NTLMEngineException {
+ try {
+ final Cipher rc4 = Cipher.getInstance("RC4");
+ rc4.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC4"));
+ return rc4.doFinal(value);
+ } catch (final Exception e) {
+ throw new NTLMEngineException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Calculates the NTLM2 Session Response for the given challenge, using the
+ * specified password and client challenge.
+ *
+ * @return The NTLM2 Session Response. This is placed in the NTLM response
+ * field of the Type 3 message; the LM response field contains the
+ * client challenge, null-padded to 24 bytes.
+ */
+ static byte[] ntlm2SessionResponse(final byte[] ntlmHash, final byte[] challenge,
+ final byte[] clientChallenge) throws NTLMEngineException {
+ try {
+ // Look up MD5 algorithm (was necessary on jdk 1.4.2)
+ // This used to be needed, but java 1.5.0_07 includes the MD5
+ // algorithm (finally)
+ // Class x = Class.forName("gnu.crypto.hash.MD5");
+ // Method updateMethod = x.getMethod("update",new
+ // Class[]{byte[].class});
+ // Method digestMethod = x.getMethod("digest",new Class[0]);
+ // Object mdInstance = x.newInstance();
+ // updateMethod.invoke(mdInstance,new Object[]{challenge});
+ // updateMethod.invoke(mdInstance,new Object[]{clientChallenge});
+ // byte[] digest = (byte[])digestMethod.invoke(mdInstance,new
+ // Object[0]);
+
+ final MessageDigest md5 = MessageDigest.getInstance("MD5");
+ md5.update(challenge);
+ md5.update(clientChallenge);
+ final byte[] digest = md5.digest();
+
+ final byte[] sessionHash = new byte[8];
+ System.arraycopy(digest, 0, sessionHash, 0, 8);
+ return lmResponse(ntlmHash, sessionHash);
+ } catch (final Exception e) {
+ if (e instanceof NTLMEngineException) {
+ throw (NTLMEngineException) e;
+ }
+ throw new NTLMEngineException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Creates the LM Hash of the user's password.
+ *
+ * @param password
+ * The password.
+ *
+ * @return The LM Hash of the given password, used in the calculation of the
+ * LM Response.
+ */
+ private static byte[] lmHash(final String password) throws NTLMEngineException {
+ try {
+ final byte[] oemPassword = password.toUpperCase(Locale.ENGLISH).getBytes("US-ASCII");
+ final int length = Math.min(oemPassword.length, 14);
+ final byte[] keyBytes = new byte[14];
+ System.arraycopy(oemPassword, 0, keyBytes, 0, length);
+ final Key lowKey = createDESKey(keyBytes, 0);
+ final Key highKey = createDESKey(keyBytes, 7);
+ final byte[] magicConstant = "KGS!@#$%".getBytes("US-ASCII");
+ final Cipher des = Cipher.getInstance("DES/ECB/NoPadding");
+ des.init(Cipher.ENCRYPT_MODE, lowKey);
+ final byte[] lowHash = des.doFinal(magicConstant);
+ des.init(Cipher.ENCRYPT_MODE, highKey);
+ final byte[] highHash = des.doFinal(magicConstant);
+ final byte[] lmHash = new byte[16];
+ System.arraycopy(lowHash, 0, lmHash, 0, 8);
+ System.arraycopy(highHash, 0, lmHash, 8, 8);
+ return lmHash;
+ } catch (final Exception e) {
+ throw new NTLMEngineException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Creates the NTLM Hash of the user's password.
+ *
+ * @param password
+ * The password.
+ *
+ * @return The NTLM Hash of the given password, used in the calculation of
+ * the NTLM Response and the NTLMv2 and LMv2 Hashes.
+ */
+ private static byte[] ntlmHash(final String password) throws NTLMEngineException {
+ try {
+ final byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked");
+ final MD4 md4 = new MD4();
+ md4.update(unicodePassword);
+ return md4.getOutput();
+ } catch (final UnsupportedEncodingException e) {
+ throw new NTLMEngineException("Unicode not supported: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Creates the LMv2 Hash of the user's password.
+ *
+ * @return The LMv2 Hash, used in the calculation of the NTLMv2 and LMv2
+ * Responses.
+ */
+ private static byte[] lmv2Hash(final String domain, final String user, final byte[] ntlmHash)
+ throws NTLMEngineException {
+ try {
+ final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash);
+ // Upper case username, upper case domain!
+ hmacMD5.update(user.toUpperCase(Locale.ENGLISH).getBytes("UnicodeLittleUnmarked"));
+ if (domain != null) {
+ hmacMD5.update(domain.toUpperCase(Locale.ENGLISH).getBytes("UnicodeLittleUnmarked"));
+ }
+ return hmacMD5.getOutput();
+ } catch (final UnsupportedEncodingException e) {
+ throw new NTLMEngineException("Unicode not supported! " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Creates the NTLMv2 Hash of the user's password.
+ *
+ * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 and LMv2
+ * Responses.
+ */
+ private static byte[] ntlmv2Hash(final String domain, final String user, final byte[] ntlmHash)
+ throws NTLMEngineException {
+ try {
+ final HMACMD5 hmacMD5 = new HMACMD5(ntlmHash);
+ // Upper case username, mixed case target!!
+ hmacMD5.update(user.toUpperCase(Locale.ENGLISH).getBytes("UnicodeLittleUnmarked"));
+ if (domain != null) {
+ hmacMD5.update(domain.getBytes("UnicodeLittleUnmarked"));
+ }
+ return hmacMD5.getOutput();
+ } catch (final UnsupportedEncodingException e) {
+ throw new NTLMEngineException("Unicode not supported! " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Creates the LM Response from the given hash and Type 2 challenge.
+ *
+ * @param hash
+ * The LM or NTLM Hash.
+ * @param challenge
+ * The server challenge from the Type 2 message.
+ *
+ * @return The response (either LM or NTLM, depending on the provided hash).
+ */
+ private static byte[] lmResponse(final byte[] hash, final byte[] challenge) throws NTLMEngineException {
+ try {
+ final byte[] keyBytes = new byte[21];
+ System.arraycopy(hash, 0, keyBytes, 0, 16);
+ final Key lowKey = createDESKey(keyBytes, 0);
+ final Key middleKey = createDESKey(keyBytes, 7);
+ final Key highKey = createDESKey(keyBytes, 14);
+ final Cipher des = Cipher.getInstance("DES/ECB/NoPadding");
+ des.init(Cipher.ENCRYPT_MODE, lowKey);
+ final byte[] lowResponse = des.doFinal(challenge);
+ des.init(Cipher.ENCRYPT_MODE, middleKey);
+ final byte[] middleResponse = des.doFinal(challenge);
+ des.init(Cipher.ENCRYPT_MODE, highKey);
+ final byte[] highResponse = des.doFinal(challenge);
+ final byte[] lmResponse = new byte[24];
+ System.arraycopy(lowResponse, 0, lmResponse, 0, 8);
+ System.arraycopy(middleResponse, 0, lmResponse, 8, 8);
+ System.arraycopy(highResponse, 0, lmResponse, 16, 8);
+ return lmResponse;
+ } catch (final Exception e) {
+ throw new NTLMEngineException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Creates the LMv2 Response from the given hash, client data, and Type 2
+ * challenge.
+ *
+ * @param hash
+ * The NTLMv2 Hash.
+ * @param clientData
+ * The client data (blob or client challenge).
+ * @param challenge
+ * The server challenge from the Type 2 message.
+ *
+ * @return The response (either NTLMv2 or LMv2, depending on the client
+ * data).
+ */
+ private static byte[] lmv2Response(final byte[] hash, final byte[] challenge, final byte[] clientData)
+ throws NTLMEngineException {
+ final HMACMD5 hmacMD5 = new HMACMD5(hash);
+ hmacMD5.update(challenge);
+ hmacMD5.update(clientData);
+ final byte[] mac = hmacMD5.getOutput();
+ final byte[] lmv2Response = new byte[mac.length + clientData.length];
+ System.arraycopy(mac, 0, lmv2Response, 0, mac.length);
+ System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length);
+ return lmv2Response;
+ }
+
+ /**
+ * Creates the NTLMv2 blob from the given target information block and
+ * client challenge.
+ *
+ * @param targetInformation
+ * The target information block from the Type 2 message.
+ * @param clientChallenge
+ * The random 8-byte client challenge.
+ *
+ * @return The blob, used in the calculation of the NTLMv2 Response.
+ */
+ private static byte[] createBlob(final byte[] clientChallenge, final byte[] targetInformation, final byte[] timestamp) {
+ final byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 };
+ final byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+ final byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+ final byte[] unknown2 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+ final byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8
+ + unknown1.length + targetInformation.length + unknown2.length];
+ int offset = 0;
+ System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length);
+ offset += blobSignature.length;
+ System.arraycopy(reserved, 0, blob, offset, reserved.length);
+ offset += reserved.length;
+ System.arraycopy(timestamp, 0, blob, offset, timestamp.length);
+ offset += timestamp.length;
+ System.arraycopy(clientChallenge, 0, blob, offset, 8);
+ offset += 8;
+ System.arraycopy(unknown1, 0, blob, offset, unknown1.length);
+ offset += unknown1.length;
+ System.arraycopy(targetInformation, 0, blob, offset, targetInformation.length);
+ offset += targetInformation.length;
+ System.arraycopy(unknown2, 0, blob, offset, unknown2.length);
+ offset += unknown2.length;
+ return blob;
+ }
+
+ /**
+ * Creates a DES encryption key from the given key material.
+ *
+ * @param bytes
+ * A byte array containing the DES key material.
+ * @param offset
+ * The offset in the given byte array at which the 7-byte key
+ * material starts.
+ *
+ * @return A DES encryption key created from the key material starting at
+ * the specified offset in the given byte array.
+ */
+ private static Key createDESKey(final byte[] bytes, final int offset) {
+ final byte[] keyBytes = new byte[7];
+ System.arraycopy(bytes, offset, keyBytes, 0, 7);
+ final byte[] material = new byte[8];
+ material[0] = keyBytes[0];
+ material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1);
+ material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2);
+ material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3);
+ material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4);
+ material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5);
+ material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6);
+ material[7] = (byte) (keyBytes[6] << 1);
+ oddParity(material);
+ return new SecretKeySpec(material, "DES");
+ }
+
+ /**
+ * Applies odd parity to the given byte array.
+ *
+ * @param bytes
+ * The data whose parity bits are to be adjusted for odd parity.
+ */
+ private static void oddParity(final byte[] bytes) {
+ for (int i = 0; i < bytes.length; i++) {
+ final byte b = bytes[i];
+ final boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3)
+ ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0;
+ if (needsParity) {
+ bytes[i] |= (byte) 0x01;
+ } else {
+ bytes[i] &= (byte) 0xfe;
+ }
+ }
+ }
+
+ /** NTLM message generation, base class */
+ static class NTLMMessage {
+ /** The current response */
+ private byte[] messageContents = null;
+
+ /** The current output position */
+ private int currentOutputPosition = 0;
+
+ /** Constructor to use when message contents are not yet known */
+ NTLMMessage() {
+ }
+
+ /** Constructor to use when message contents are known */
+ NTLMMessage(final String messageBody, final int expectedType) throws NTLMEngineException {
+ messageContents = Base64.decodeBase64(EncodingUtils.getBytes(messageBody,
+ DEFAULT_CHARSET));
+ // Look for NTLM message
+ if (messageContents.length < SIGNATURE.length) {
+ throw new NTLMEngineException("NTLM message decoding error - packet too short");
+ }
+ int i = 0;
+ while (i < SIGNATURE.length) {
+ if (messageContents[i] != SIGNATURE[i]) {
+ throw new NTLMEngineException(
+ "NTLM message expected - instead got unrecognized bytes");
+ }
+ i++;
+ }
+
+ // Check to be sure there's a type 2 message indicator next
+ final int type = readULong(SIGNATURE.length);
+ if (type != expectedType) {
+ throw new NTLMEngineException("NTLM type " + Integer.toString(expectedType)
+ + " message expected - instead got type " + Integer.toString(type));
+ }
+
+ currentOutputPosition = messageContents.length;
+ }
+
+ /**
+ * Get the length of the signature and flags, so calculations can adjust
+ * offsets accordingly.
+ */
+ protected int getPreambleLength() {
+ return SIGNATURE.length + 4;
+ }
+
+ /** Get the message length */
+ protected int getMessageLength() {
+ return currentOutputPosition;
+ }
+
+ /** Read a byte from a position within the message buffer */
+ protected byte readByte(final int position) throws NTLMEngineException {
+ if (messageContents.length < position + 1) {
+ throw new NTLMEngineException("NTLM: Message too short");
+ }
+ return messageContents[position];
+ }
+
+ /** Read a bunch of bytes from a position in the message buffer */
+ protected void readBytes(final byte[] buffer, final int position) throws NTLMEngineException {
+ if (messageContents.length < position + buffer.length) {
+ throw new NTLMEngineException("NTLM: Message too short");
+ }
+ System.arraycopy(messageContents, position, buffer, 0, buffer.length);
+ }
+
+ /** Read a ushort from a position within the message buffer */
+ protected int readUShort(final int position) throws NTLMEngineException {
+ return NTLMEngineImpl.readUShort(messageContents, position);
+ }
+
+ /** Read a ulong from a position within the message buffer */
+ protected int readULong(final int position) throws NTLMEngineException {
+ return NTLMEngineImpl.readULong(messageContents, position);
+ }
+
+ /** Read a security buffer from a position within the message buffer */
+ protected byte[] readSecurityBuffer(final int position) throws NTLMEngineException {
+ return NTLMEngineImpl.readSecurityBuffer(messageContents, position);
+ }
+
+ /**
+ * Prepares the object to create a response of the given length.
+ *
+ * @param maxlength
+ * the maximum length of the response to prepare, not
+ * including the type and the signature (which this method
+ * adds).
+ */
+ protected void prepareResponse(final int maxlength, final int messageType) {
+ messageContents = new byte[maxlength];
+ currentOutputPosition = 0;
+ addBytes(SIGNATURE);
+ addULong(messageType);
+ }
+
+ /**
+ * Adds the given byte to the response.
+ *
+ * @param b
+ * the byte to add.
+ */
+ protected void addByte(final byte b) {
+ messageContents[currentOutputPosition] = b;
+ currentOutputPosition++;
+ }
+
+ /**
+ * Adds the given bytes to the response.
+ *
+ * @param bytes
+ * the bytes to add.
+ */
+ protected void addBytes(final byte[] bytes) {
+ if (bytes == null) {
+ return;
+ }
+ for (final byte b : bytes) {
+ messageContents[currentOutputPosition] = b;
+ currentOutputPosition++;
+ }
+ }
+
+ /** Adds a USHORT to the response */
+ protected void addUShort(final int value) {
+ addByte((byte) (value & 0xff));
+ addByte((byte) (value >> 8 & 0xff));
+ }
+
+ /** Adds a ULong to the response */
+ protected void addULong(final int value) {
+ addByte((byte) (value & 0xff));
+ addByte((byte) (value >> 8 & 0xff));
+ addByte((byte) (value >> 16 & 0xff));
+ addByte((byte) (value >> 24 & 0xff));
+ }
+
+ /**
+ * Returns the response that has been generated after shrinking the
+ * array if required and base64 encodes the response.
+ *
+ * @return The response as above.
+ */
+ String getResponse() {
+ final byte[] resp;
+ if (messageContents.length > currentOutputPosition) {
+ final byte[] tmp = new byte[currentOutputPosition];
+ System.arraycopy(messageContents, 0, tmp, 0, currentOutputPosition);
+ resp = tmp;
+ } else {
+ resp = messageContents;
+ }
+ return EncodingUtils.getAsciiString(Base64.encodeBase64(resp));
+ }
+
+ }
+
+ /** Type 1 message assembly class */
+ static class Type1Message extends NTLMMessage {
+ protected byte[] hostBytes;
+ protected byte[] domainBytes;
+
+ /** Constructor. Include the arguments the message will need */
+ Type1Message(final String domain, final String host) throws NTLMEngineException {
+ super();
+ try {
+ // Strip off domain name from the host!
+ final String unqualifiedHost = convertHost(host);
+ // Use only the base domain name!
+ final String unqualifiedDomain = convertDomain(domain);
+
+ hostBytes = unqualifiedHost != null? unqualifiedHost.getBytes("ASCII") : null;
+ domainBytes = unqualifiedDomain != null ? unqualifiedDomain
+ .toUpperCase(Locale.ENGLISH).getBytes("ASCII") : null;
+ } catch (final UnsupportedEncodingException e) {
+ throw new NTLMEngineException("Unicode unsupported: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Getting the response involves building the message before returning
+ * it
+ */
+ @Override
+ String getResponse() {
+ // Now, build the message. Calculate its length first, including
+ // signature or type.
+ final int finalLength = 32 + 8 /*+ hostBytes.length + domainBytes.length */;
+
+ // Set up the response. This will initialize the signature, message
+ // type, and flags.
+ prepareResponse(finalLength, 1);
+
+ // Flags. These are the complete set of flags we support.
+ addULong(
+ //FLAG_WORKSTATION_PRESENT |
+ //FLAG_DOMAIN_PRESENT |
+
+ // Required flags
+ //FLAG_REQUEST_LAN_MANAGER_KEY |
+ FLAG_REQUEST_NTLMv1 |
+ FLAG_REQUEST_NTLM2_SESSION |
+
+ // Protocol version request
+ FLAG_REQUEST_VERSION |
+
+ // Recommended privacy settings
+ FLAG_REQUEST_ALWAYS_SIGN |
+ //FLAG_REQUEST_SEAL |
+ //FLAG_REQUEST_SIGN |
+
+ // These must be set according to documentation, based on use of SEAL above
+ FLAG_REQUEST_128BIT_KEY_EXCH |
+ FLAG_REQUEST_56BIT_ENCRYPTION |
+ //FLAG_REQUEST_EXPLICIT_KEY_EXCH |
+
+ FLAG_REQUEST_UNICODE_ENCODING);
+
+ // Domain length (two times).
+ addUShort(/*domainBytes.length*/0);
+ addUShort(/*domainBytes.length*/0);
+
+ // Domain offset.
+ addULong(/*hostBytes.length +*/ 32 + 8);
+
+ // Host length (two times).
+ addUShort(/*hostBytes.length*/0);
+ addUShort(/*hostBytes.length*/0);
+
+ // Host offset (always 32 + 8).
+ addULong(32 + 8);
+
+ // Version
+ addUShort(0x0105);
+ // Build
+ addULong(2600);
+ // NTLM revision
+ addUShort(0x0f00);
+
+
+ // Host (workstation) String.
+ //addBytes(hostBytes);
+
+ // Domain String.
+ //addBytes(domainBytes);
+
+
+ return super.getResponse();
+ }
+
+ }
+
+ /** Type 2 message class */
+ static class Type2Message extends NTLMMessage {
+ protected byte[] challenge;
+ protected String target;
+ protected byte[] targetInfo;
+ protected int flags;
+
+ Type2Message(final String message) throws NTLMEngineException {
+ super(message, 2);
+
+ // Type 2 message is laid out as follows:
+ // First 8 bytes: NTLMSSP[0]
+ // Next 4 bytes: Ulong, value 2
+ // Next 8 bytes, starting at offset 12: target field (2 ushort lengths, 1 ulong offset)
+ // Next 4 bytes, starting at offset 20: Flags, e.g. 0x22890235
+ // Next 8 bytes, starting at offset 24: Challenge
+ // Next 8 bytes, starting at offset 32: ??? (8 bytes of zeros)
+ // Next 8 bytes, starting at offset 40: targetinfo field (2 ushort lengths, 1 ulong offset)
+ // Next 2 bytes, major/minor version number (e.g. 0x05 0x02)
+ // Next 8 bytes, build number
+ // Next 2 bytes, protocol version number (e.g. 0x00 0x0f)
+ // Next, various text fields, and a ushort of value 0 at the end
+
+ // Parse out the rest of the info we need from the message
+ // The nonce is the 8 bytes starting from the byte in position 24.
+ challenge = new byte[8];
+ readBytes(challenge, 24);
+
+ flags = readULong(20);
+
+ if ((flags & FLAG_REQUEST_UNICODE_ENCODING) == 0) {
+ throw new NTLMEngineException(
+ "NTLM type 2 message has flags that make no sense: "
+ + Integer.toString(flags));
+ }
+
+ // Do the target!
+ target = null;
+ // The TARGET_DESIRED flag is said to not have understood semantics
+ // in Type2 messages, so use the length of the packet to decide
+ // how to proceed instead
+ if (getMessageLength() >= 12 + 8) {
+ final byte[] bytes = readSecurityBuffer(12);
+ if (bytes.length != 0) {
+ try {
+ target = new String(bytes, "UnicodeLittleUnmarked");
+ } catch (final UnsupportedEncodingException e) {
+ throw new NTLMEngineException(e.getMessage(), e);
+ }
+ }
+ }
+
+ // Do the target info!
+ targetInfo = null;
+ // TARGET_DESIRED flag cannot be relied on, so use packet length
+ if (getMessageLength() >= 40 + 8) {
+ final byte[] bytes = readSecurityBuffer(40);
+ if (bytes.length != 0) {
+ targetInfo = bytes;
+ }
+ }
+ }
+
+ /** Retrieve the challenge */
+ byte[] getChallenge() {
+ return challenge;
+ }
+
+ /** Retrieve the target */
+ String getTarget() {
+ return target;
+ }
+
+ /** Retrieve the target info */
+ byte[] getTargetInfo() {
+ return targetInfo;
+ }
+
+ /** Retrieve the response flags */
+ int getFlags() {
+ return flags;
+ }
+
+ }
+
+ /** Type 3 message assembly class */
+ static class Type3Message extends NTLMMessage {
+ // Response flags from the type2 message
+ protected int type2Flags;
+
+ protected byte[] domainBytes;
+ protected byte[] hostBytes;
+ protected byte[] userBytes;
+
+ protected byte[] lmResp;
+ protected byte[] ntResp;
+ protected byte[] sessionKey;
+
+
+ /** Constructor. Pass the arguments we will need */
+ Type3Message(final String domain, final String host, final String user, final String password, final byte[] nonce,
+ final int type2Flags, final String target, final byte[] targetInformation)
+ throws NTLMEngineException {
+ // Save the flags
+ this.type2Flags = type2Flags;
+
+ // Strip off domain name from the host!
+ final String unqualifiedHost = convertHost(host);
+ // Use only the base domain name!
+ final String unqualifiedDomain = convertDomain(domain);
+
+ // Create a cipher generator class. Use domain BEFORE it gets modified!
+ final CipherGen gen = new CipherGen(unqualifiedDomain, user, password, nonce, target, targetInformation);
+
+ // Use the new code to calculate the responses, including v2 if that
+ // seems warranted.
+ byte[] userSessionKey;
+ try {
+ // This conditional may not work on Windows Server 2008 R2 and above, where it has not yet
+ // been tested
+ if (((type2Flags & FLAG_TARGETINFO_PRESENT) != 0) &&
+ targetInformation != null && target != null) {
+ // NTLMv2
+ ntResp = gen.getNTLMv2Response();
+ lmResp = gen.getLMv2Response();
+ if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) {
+ userSessionKey = gen.getLanManagerSessionKey();
+ } else {
+ userSessionKey = gen.getNTLMv2UserSessionKey();
+ }
+ } else {
+ // NTLMv1
+ if ((type2Flags & FLAG_REQUEST_NTLM2_SESSION) != 0) {
+ // NTLM2 session stuff is requested
+ ntResp = gen.getNTLM2SessionResponse();
+ lmResp = gen.getLM2SessionResponse();
+ if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) {
+ userSessionKey = gen.getLanManagerSessionKey();
+ } else {
+ userSessionKey = gen.getNTLM2SessionResponseUserSessionKey();
+ }
+ } else {
+ ntResp = gen.getNTLMResponse();
+ lmResp = gen.getLMResponse();
+ if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) {
+ userSessionKey = gen.getLanManagerSessionKey();
+ } else {
+ userSessionKey = gen.getNTLMUserSessionKey();
+ }
+ }
+ }
+ } catch (final NTLMEngineException e) {
+ // This likely means we couldn't find the MD4 hash algorithm -
+ // fail back to just using LM
+ ntResp = new byte[0];
+ lmResp = gen.getLMResponse();
+ if ((type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) != 0) {
+ userSessionKey = gen.getLanManagerSessionKey();
+ } else {
+ userSessionKey = gen.getLMUserSessionKey();
+ }
+ }
+
+ if ((type2Flags & FLAG_REQUEST_SIGN) != 0) {
+ if ((type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) != 0) {
+ sessionKey = RC4(gen.getSecondaryKey(), userSessionKey);
+ } else {
+ sessionKey = userSessionKey;
+ }
+ } else {
+ sessionKey = null;
+ }
+
+ try {
+ hostBytes = unqualifiedHost != null ? unqualifiedHost
+ .getBytes("UnicodeLittleUnmarked") : null;
+ domainBytes = unqualifiedDomain != null ? unqualifiedDomain
+ .toUpperCase(Locale.ENGLISH).getBytes("UnicodeLittleUnmarked") : null;
+ userBytes = user.getBytes("UnicodeLittleUnmarked");
+ } catch (final UnsupportedEncodingException e) {
+ throw new NTLMEngineException("Unicode not supported: " + e.getMessage(), e);
+ }
+ }
+
+ /** Assemble the response */
+ @Override
+ String getResponse() {
+ final int ntRespLen = ntResp.length;
+ final int lmRespLen = lmResp.length;
+
+ final int domainLen = domainBytes != null ? domainBytes.length : 0;
+ final int hostLen = hostBytes != null ? hostBytes.length: 0;
+ final int userLen = userBytes.length;
+ final int sessionKeyLen;
+ if (sessionKey != null) {
+ sessionKeyLen = sessionKey.length;
+ } else {
+ sessionKeyLen = 0;
+ }
+
+ // Calculate the layout within the packet
+ final int lmRespOffset = 72; // allocate space for the version
+ final int ntRespOffset = lmRespOffset + lmRespLen;
+ final int domainOffset = ntRespOffset + ntRespLen;
+ final int userOffset = domainOffset + domainLen;
+ final int hostOffset = userOffset + userLen;
+ final int sessionKeyOffset = hostOffset + hostLen;
+ final int finalLength = sessionKeyOffset + sessionKeyLen;
+
+ // Start the response. Length includes signature and type
+ prepareResponse(finalLength, 3);
+
+ // LM Resp Length (twice)
+ addUShort(lmRespLen);
+ addUShort(lmRespLen);
+
+ // LM Resp Offset
+ addULong(lmRespOffset);
+
+ // NT Resp Length (twice)
+ addUShort(ntRespLen);
+ addUShort(ntRespLen);
+
+ // NT Resp Offset
+ addULong(ntRespOffset);
+
+ // Domain length (twice)
+ addUShort(domainLen);
+ addUShort(domainLen);
+
+ // Domain offset.
+ addULong(domainOffset);
+
+ // User Length (twice)
+ addUShort(userLen);
+ addUShort(userLen);
+
+ // User offset
+ addULong(userOffset);
+
+ // Host length (twice)
+ addUShort(hostLen);
+ addUShort(hostLen);
+
+ // Host offset
+ addULong(hostOffset);
+
+ // Session key length (twice)
+ addUShort(sessionKeyLen);
+ addUShort(sessionKeyLen);
+
+ // Session key offset
+ addULong(sessionKeyOffset);
+
+ // Flags.
+ addULong(
+ //FLAG_WORKSTATION_PRESENT |
+ //FLAG_DOMAIN_PRESENT |
+
+ // Required flags
+ (type2Flags & FLAG_REQUEST_LAN_MANAGER_KEY) |
+ (type2Flags & FLAG_REQUEST_NTLMv1) |
+ (type2Flags & FLAG_REQUEST_NTLM2_SESSION) |
+
+ // Protocol version request
+ FLAG_REQUEST_VERSION |
+
+ // Recommended privacy settings
+ (type2Flags & FLAG_REQUEST_ALWAYS_SIGN) |
+ (type2Flags & FLAG_REQUEST_SEAL) |
+ (type2Flags & FLAG_REQUEST_SIGN) |
+
+ // These must be set according to documentation, based on use of SEAL above
+ (type2Flags & FLAG_REQUEST_128BIT_KEY_EXCH) |
+ (type2Flags & FLAG_REQUEST_56BIT_ENCRYPTION) |
+ (type2Flags & FLAG_REQUEST_EXPLICIT_KEY_EXCH) |
+
+ (type2Flags & FLAG_TARGETINFO_PRESENT) |
+ (type2Flags & FLAG_REQUEST_UNICODE_ENCODING) |
+ (type2Flags & FLAG_REQUEST_TARGET)
+ );
+
+ // Version
+ addUShort(0x0105);
+ // Build
+ addULong(2600);
+ // NTLM revision
+ addUShort(0x0f00);
+
+ // Add the actual data
+ addBytes(lmResp);
+ addBytes(ntResp);
+ addBytes(domainBytes);
+ addBytes(userBytes);
+ addBytes(hostBytes);
+ if (sessionKey != null) {
+ addBytes(sessionKey);
+ }
+
+ return super.getResponse();
+ }
+ }
+
+ static void writeULong(final byte[] buffer, final int value, final int offset) {
+ buffer[offset] = (byte) (value & 0xff);
+ buffer[offset + 1] = (byte) (value >> 8 & 0xff);
+ buffer[offset + 2] = (byte) (value >> 16 & 0xff);
+ buffer[offset + 3] = (byte) (value >> 24 & 0xff);
+ }
+
+ static int F(final int x, final int y, final int z) {
+ return ((x & y) | (~x & z));
+ }
+
+ static int G(final int x, final int y, final int z) {
+ return ((x & y) | (x & z) | (y & z));
+ }
+
+ static int H(final int x, final int y, final int z) {
+ return (x ^ y ^ z);
+ }
+
+ static int rotintlft(final int val, final int numbits) {
+ return ((val << numbits) | (val >>> (32 - numbits)));
+ }
+
+ /**
+ * Cryptography support - MD4. The following class was based loosely on the
+ * RFC and on code found at http://www.cs.umd.edu/~harry/jotp/src/md.java.
+ * Code correctness was verified by looking at MD4.java from the jcifs
+ * library (http://jcifs.samba.org). It was massaged extensively to the
+ * final form found here by Karl Wright (kwright@metacarta.com).
+ */
+ static class MD4 {
+ protected int A = 0x67452301;
+ protected int B = 0xefcdab89;
+ protected int C = 0x98badcfe;
+ protected int D = 0x10325476;
+ protected long count = 0L;
+ protected byte[] dataBuffer = new byte[64];
+
+ MD4() {
+ }
+
+ void update(final byte[] input) {
+ // We always deal with 512 bits at a time. Correspondingly, there is
+ // a buffer 64 bytes long that we write data into until it gets
+ // full.
+ int curBufferPos = (int) (count & 63L);
+ int inputIndex = 0;
+ while (input.length - inputIndex + curBufferPos >= dataBuffer.length) {
+ // We have enough data to do the next step. Do a partial copy
+ // and a transform, updating inputIndex and curBufferPos
+ // accordingly
+ final int transferAmt = dataBuffer.length - curBufferPos;
+ System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt);
+ count += transferAmt;
+ curBufferPos = 0;
+ inputIndex += transferAmt;
+ processBuffer();
+ }
+
+ // If there's anything left, copy it into the buffer and leave it.
+ // We know there's not enough left to process.
+ if (inputIndex < input.length) {
+ final int transferAmt = input.length - inputIndex;
+ System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt);
+ count += transferAmt;
+ curBufferPos += transferAmt;
+ }
+ }
+
+ byte[] getOutput() {
+ // Feed pad/length data into engine. This must round out the input
+ // to a multiple of 512 bits.
+ final int bufferIndex = (int) (count & 63L);
+ final int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex);
+ final byte[] postBytes = new byte[padLen + 8];
+ // Leading 0x80, specified amount of zero padding, then length in
+ // bits.
+ postBytes[0] = (byte) 0x80;
+ // Fill out the last 8 bytes with the length
+ for (int i = 0; i < 8; i++) {
+ postBytes[padLen + i] = (byte) ((count * 8) >>> (8 * i));
+ }
+
+ // Update the engine
+ update(postBytes);
+
+ // Calculate final result
+ final byte[] result = new byte[16];
+ writeULong(result, A, 0);
+ writeULong(result, B, 4);
+ writeULong(result, C, 8);
+ writeULong(result, D, 12);
+ return result;
+ }
+
+ protected void processBuffer() {
+ // Convert current buffer to 16 ulongs
+ final int[] d = new int[16];
+
+ for (int i = 0; i < 16; i++) {
+ d[i] = (dataBuffer[i * 4] & 0xff) + ((dataBuffer[i * 4 + 1] & 0xff) << 8)
+ + ((dataBuffer[i * 4 + 2] & 0xff) << 16)
+ + ((dataBuffer[i * 4 + 3] & 0xff) << 24);
+ }
+
+ // Do a round of processing
+ final int AA = A;
+ final int BB = B;
+ final int CC = C;
+ final int DD = D;
+ round1(d);
+ round2(d);
+ round3(d);
+ A += AA;
+ B += BB;
+ C += CC;
+ D += DD;
+
+ }
+
+ protected void round1(final int[] d) {
+ A = rotintlft((A + F(B, C, D) + d[0]), 3);
+ D = rotintlft((D + F(A, B, C) + d[1]), 7);
+ C = rotintlft((C + F(D, A, B) + d[2]), 11);
+ B = rotintlft((B + F(C, D, A) + d[3]), 19);
+
+ A = rotintlft((A + F(B, C, D) + d[4]), 3);
+ D = rotintlft((D + F(A, B, C) + d[5]), 7);
+ C = rotintlft((C + F(D, A, B) + d[6]), 11);
+ B = rotintlft((B + F(C, D, A) + d[7]), 19);
+
+ A = rotintlft((A + F(B, C, D) + d[8]), 3);
+ D = rotintlft((D + F(A, B, C) + d[9]), 7);
+ C = rotintlft((C + F(D, A, B) + d[10]), 11);
+ B = rotintlft((B + F(C, D, A) + d[11]), 19);
+
+ A = rotintlft((A + F(B, C, D) + d[12]), 3);
+ D = rotintlft((D + F(A, B, C) + d[13]), 7);
+ C = rotintlft((C + F(D, A, B) + d[14]), 11);
+ B = rotintlft((B + F(C, D, A) + d[15]), 19);
+ }
+
+ protected void round2(final int[] d) {
+ A = rotintlft((A + G(B, C, D) + d[0] + 0x5a827999), 3);
+ D = rotintlft((D + G(A, B, C) + d[4] + 0x5a827999), 5);
+ C = rotintlft((C + G(D, A, B) + d[8] + 0x5a827999), 9);
+ B = rotintlft((B + G(C, D, A) + d[12] + 0x5a827999), 13);
+
+ A = rotintlft((A + G(B, C, D) + d[1] + 0x5a827999), 3);
+ D = rotintlft((D + G(A, B, C) + d[5] + 0x5a827999), 5);
+ C = rotintlft((C + G(D, A, B) + d[9] + 0x5a827999), 9);
+ B = rotintlft((B + G(C, D, A) + d[13] + 0x5a827999), 13);
+
+ A = rotintlft((A + G(B, C, D) + d[2] + 0x5a827999), 3);
+ D = rotintlft((D + G(A, B, C) + d[6] + 0x5a827999), 5);
+ C = rotintlft((C + G(D, A, B) + d[10] + 0x5a827999), 9);
+ B = rotintlft((B + G(C, D, A) + d[14] + 0x5a827999), 13);
+
+ A = rotintlft((A + G(B, C, D) + d[3] + 0x5a827999), 3);
+ D = rotintlft((D + G(A, B, C) + d[7] + 0x5a827999), 5);
+ C = rotintlft((C + G(D, A, B) + d[11] + 0x5a827999), 9);
+ B = rotintlft((B + G(C, D, A) + d[15] + 0x5a827999), 13);
+
+ }
+
+ protected void round3(final int[] d) {
+ A = rotintlft((A + H(B, C, D) + d[0] + 0x6ed9eba1), 3);
+ D = rotintlft((D + H(A, B, C) + d[8] + 0x6ed9eba1), 9);
+ C = rotintlft((C + H(D, A, B) + d[4] + 0x6ed9eba1), 11);
+ B = rotintlft((B + H(C, D, A) + d[12] + 0x6ed9eba1), 15);
+
+ A = rotintlft((A + H(B, C, D) + d[2] + 0x6ed9eba1), 3);
+ D = rotintlft((D + H(A, B, C) + d[10] + 0x6ed9eba1), 9);
+ C = rotintlft((C + H(D, A, B) + d[6] + 0x6ed9eba1), 11);
+ B = rotintlft((B + H(C, D, A) + d[14] + 0x6ed9eba1), 15);
+
+ A = rotintlft((A + H(B, C, D) + d[1] + 0x6ed9eba1), 3);
+ D = rotintlft((D + H(A, B, C) + d[9] + 0x6ed9eba1), 9);
+ C = rotintlft((C + H(D, A, B) + d[5] + 0x6ed9eba1), 11);
+ B = rotintlft((B + H(C, D, A) + d[13] + 0x6ed9eba1), 15);
+
+ A = rotintlft((A + H(B, C, D) + d[3] + 0x6ed9eba1), 3);
+ D = rotintlft((D + H(A, B, C) + d[11] + 0x6ed9eba1), 9);
+ C = rotintlft((C + H(D, A, B) + d[7] + 0x6ed9eba1), 11);
+ B = rotintlft((B + H(C, D, A) + d[15] + 0x6ed9eba1), 15);
+
+ }
+
+ }
+
+ /**
+ * Cryptography support - HMACMD5 - algorithmically based on various web
+ * resources by Karl Wright
+ */
+ static class HMACMD5 {
+ protected byte[] ipad;
+ protected byte[] opad;
+ protected MessageDigest md5;
+
+ HMACMD5(final byte[] input) throws NTLMEngineException {
+ byte[] key = input;
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ } catch (final Exception ex) {
+ // Umm, the algorithm doesn't exist - throw an
+ // NTLMEngineException!
+ throw new NTLMEngineException(
+ "Error getting md5 message digest implementation: " + ex.getMessage(), ex);
+ }
+
+ // Initialize the pad buffers with the key
+ ipad = new byte[64];
+ opad = new byte[64];
+
+ int keyLength = key.length;
+ if (keyLength > 64) {
+ // Use MD5 of the key instead, as described in RFC 2104
+ md5.update(key);
+ key = md5.digest();
+ keyLength = key.length;
+ }
+ int i = 0;
+ while (i < keyLength) {
+ ipad[i] = (byte) (key[i] ^ (byte) 0x36);
+ opad[i] = (byte) (key[i] ^ (byte) 0x5c);
+ i++;
+ }
+ while (i < 64) {
+ ipad[i] = (byte) 0x36;
+ opad[i] = (byte) 0x5c;
+ i++;
+ }
+
+ // Very important: update the digest with the ipad buffer
+ md5.reset();
+ md5.update(ipad);
+
+ }
+
+ /** Grab the current digest. This is the "answer". */
+ byte[] getOutput() {
+ final byte[] digest = md5.digest();
+ md5.update(opad);
+ return md5.digest(digest);
+ }
+
+ /** Update by adding a complete array */
+ void update(final byte[] input) {
+ md5.update(input);
+ }
+
+ /** Update the algorithm */
+ void update(final byte[] input, final int offset, final int length) {
+ md5.update(input, offset, length);
+ }
+
+ }
+
+ public String generateType1Msg(
+ final String domain,
+ final String workstation) throws NTLMEngineException {
+ return getType1Message(workstation, domain);
+ }
+
+ public String generateType3Msg(
+ final String username,
+ final String password,
+ final String domain,
+ final String workstation,
+ final String challenge) throws NTLMEngineException {
+ final Type2Message t2m = new Type2Message(challenge);
+ return getType3Message(
+ username,
+ password,
+ workstation,
+ domain,
+ t2m.getChallenge(),
+ t2m.getFlags(),
+ t2m.getTarget(),
+ t2m.getTargetInfo());
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMScheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMScheme.java
new file mode 100644
index 000000000..68873954b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMScheme.java
@@ -0,0 +1,164 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.InvalidCredentialsException;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.auth.NTCredentials;
+import ch.boye.httpclientandroidlib.message.BufferedHeader;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * NTLM is a proprietary authentication scheme developed by Microsoft
+ * and optimized for Windows platforms.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class NTLMScheme extends AuthSchemeBase {
+
+ enum State {
+ UNINITIATED,
+ CHALLENGE_RECEIVED,
+ MSG_TYPE1_GENERATED,
+ MSG_TYPE2_RECEVIED,
+ MSG_TYPE3_GENERATED,
+ FAILED,
+ }
+
+ private final NTLMEngine engine;
+
+ private State state;
+ private String challenge;
+
+ public NTLMScheme(final NTLMEngine engine) {
+ super();
+ Args.notNull(engine, "NTLM engine");
+ this.engine = engine;
+ this.state = State.UNINITIATED;
+ this.challenge = null;
+ }
+
+ /**
+ * @since 4.3
+ */
+ public NTLMScheme() {
+ this(new NTLMEngineImpl());
+ }
+
+ public String getSchemeName() {
+ return "ntlm";
+ }
+
+ public String getParameter(final String name) {
+ // String parameters not supported
+ return null;
+ }
+
+ public String getRealm() {
+ // NTLM does not support the concept of an authentication realm
+ return null;
+ }
+
+ public boolean isConnectionBased() {
+ return true;
+ }
+
+ @Override
+ protected void parseChallenge(
+ final CharArrayBuffer buffer,
+ final int beginIndex, final int endIndex) throws MalformedChallengeException {
+ this.challenge = buffer.substringTrimmed(beginIndex, endIndex);
+ if (this.challenge.length() == 0) {
+ if (this.state == State.UNINITIATED) {
+ this.state = State.CHALLENGE_RECEIVED;
+ } else {
+ this.state = State.FAILED;
+ }
+ } else {
+ if (this.state.compareTo(State.MSG_TYPE1_GENERATED) < 0) {
+ this.state = State.FAILED;
+ throw new MalformedChallengeException("Out of sequence NTLM response message");
+ } else if (this.state == State.MSG_TYPE1_GENERATED) {
+ this.state = State.MSG_TYPE2_RECEVIED;
+ }
+ }
+ }
+
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request) throws AuthenticationException {
+ NTCredentials ntcredentials = null;
+ try {
+ ntcredentials = (NTCredentials) credentials;
+ } catch (final ClassCastException e) {
+ throw new InvalidCredentialsException(
+ "Credentials cannot be used for NTLM authentication: "
+ + credentials.getClass().getName());
+ }
+ String response = null;
+ if (this.state == State.FAILED) {
+ throw new AuthenticationException("NTLM authentication failed");
+ } else if (this.state == State.CHALLENGE_RECEIVED) {
+ response = this.engine.generateType1Msg(
+ ntcredentials.getDomain(),
+ ntcredentials.getWorkstation());
+ this.state = State.MSG_TYPE1_GENERATED;
+ } else if (this.state == State.MSG_TYPE2_RECEVIED) {
+ response = this.engine.generateType3Msg(
+ ntcredentials.getUserName(),
+ ntcredentials.getPassword(),
+ ntcredentials.getDomain(),
+ ntcredentials.getWorkstation(),
+ this.challenge);
+ this.state = State.MSG_TYPE3_GENERATED;
+ } else {
+ throw new AuthenticationException("Unexpected state: " + this.state);
+ }
+ final CharArrayBuffer buffer = new CharArrayBuffer(32);
+ if (isProxy()) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": NTLM ");
+ buffer.append(response);
+ return new BufferedHeader(buffer);
+ }
+
+ public boolean isComplete() {
+ return this.state == State.MSG_TYPE3_GENERATED || this.state == State.FAILED;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMSchemeFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMSchemeFactory.java
new file mode 100644
index 000000000..0484df643
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/NTLMSchemeFactory.java
@@ -0,0 +1,56 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeFactory;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link AuthSchemeProvider} implementation that creates and initializes
+ * {@link NTLMScheme} instances configured to use the default {@link NTLMEngine}
+ * implementation.
+ *
+ * @since 4.1
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class NTLMSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider {
+
+ public AuthScheme newInstance(final HttpParams params) {
+ return new NTLMScheme();
+ }
+
+ public AuthScheme create(final HttpContext context) {
+ return new NTLMScheme();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/RFC2617Scheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/RFC2617Scheme.java
new file mode 100644
index 000000000..93d1bf843
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/RFC2617Scheme.java
@@ -0,0 +1,151 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.ChallengeState;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.auth.params.AuthPNames;
+import ch.boye.httpclientandroidlib.message.BasicHeaderValueParser;
+import ch.boye.httpclientandroidlib.message.HeaderValueParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract authentication scheme class that lays foundation for all
+ * RFC 2617 compliant authentication schemes and provides capabilities common
+ * to all authentication schemes defined in RFC 2617.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe // AuthSchemeBase, params
+public abstract class RFC2617Scheme extends AuthSchemeBase {
+
+ private final Map<String, String> params;
+ private final Charset credentialsCharset;
+
+ /**
+ * Creates an instance of <tt>RFC2617Scheme</tt> with the given challenge
+ * state.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public RFC2617Scheme(final ChallengeState challengeState) {
+ super(challengeState);
+ this.params = new HashMap<String, String>();
+ this.credentialsCharset = Consts.ASCII;
+ }
+
+ /**
+ * @since 4.3
+ */
+ public RFC2617Scheme(final Charset credentialsCharset) {
+ super();
+ this.params = new HashMap<String, String>();
+ this.credentialsCharset = credentialsCharset != null ? credentialsCharset : Consts.ASCII;
+ }
+
+ public RFC2617Scheme() {
+ this(Consts.ASCII);
+ }
+
+
+ /**
+ * @since 4.3
+ */
+ public Charset getCredentialsCharset() {
+ return credentialsCharset;
+ }
+
+ String getCredentialsCharset(final HttpRequest request) {
+ String charset = (String) request.getParams().getParameter(AuthPNames.CREDENTIAL_CHARSET);
+ if (charset == null) {
+ charset = getCredentialsCharset().name();
+ }
+ return charset;
+ }
+
+ @Override
+ protected void parseChallenge(
+ final CharArrayBuffer buffer, final int pos, final int len) throws MalformedChallengeException {
+ final HeaderValueParser parser = BasicHeaderValueParser.INSTANCE;
+ final ParserCursor cursor = new ParserCursor(pos, buffer.length());
+ final HeaderElement[] elements = parser.parseElements(buffer, cursor);
+ if (elements.length == 0) {
+ throw new MalformedChallengeException("Authentication challenge is empty");
+ }
+ this.params.clear();
+ for (final HeaderElement element : elements) {
+ this.params.put(element.getName().toLowerCase(Locale.ENGLISH), element.getValue());
+ }
+ }
+
+ /**
+ * Returns authentication parameters map. Keys in the map are lower-cased.
+ *
+ * @return the map of authentication parameters
+ */
+ protected Map<String, String> getParameters() {
+ return this.params;
+ }
+
+ /**
+ * Returns authentication parameter with the given name, if available.
+ *
+ * @param name The name of the parameter to be returned
+ *
+ * @return the parameter with the given name
+ */
+ public String getParameter(final String name) {
+ if (name == null) {
+ return null;
+ }
+ return this.params.get(name.toLowerCase(Locale.ENGLISH));
+ }
+
+ /**
+ * Returns authentication realm. The realm may not be null.
+ *
+ * @return the authentication realm
+ */
+ public String getRealm() {
+ return getParameter("realm");
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java
new file mode 100644
index 000000000..5ab0348ad
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import java.io.IOException;
+
+/**
+ * Abstract SPNEGO token generator. Implementations should take an Kerberos ticket and transform
+ * into a SPNEGO token.
+ * <p>
+ * Implementations of this interface are expected to be thread-safe.
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.2) subclass {@link KerberosScheme} and override
+ * {@link KerberosScheme#generateGSSToken(byte[], org.ietf.jgss.Oid, String)}
+ */
+@Deprecated
+public interface SpnegoTokenGenerator {
+
+ byte [] generateSpnegoDERObject(byte [] kerberosTicket) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java
new file mode 100644
index 000000000..71a6f892f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Authentication credentials required to respond to a authentication
+ * challenge are invalid
+ *
+ *
+ * @since 4.0
+ */
+@Immutable
+public class UnsupportedDigestAlgorithmException extends RuntimeException {
+
+ private static final long serialVersionUID = 319558534317118022L;
+
+ /**
+ * Creates a new UnsupportedAuthAlgoritmException with a <tt>null</tt> detail message.
+ */
+ public UnsupportedDigestAlgorithmException() {
+ super();
+ }
+
+ /**
+ * Creates a new UnsupportedAuthAlgoritmException with the specified message.
+ *
+ * @param message the exception detail message
+ */
+ public UnsupportedDigestAlgorithmException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new UnsupportedAuthAlgoritmException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public UnsupportedDigestAlgorithmException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/package-info.java
new file mode 100644
index 000000000..9e35c852d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/auth/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default implementations of standard and common HTTP authentication
+ * schemes.
+ */
+package ch.boye.httpclientandroidlib.impl.auth;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AIMDBackoffManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AIMDBackoffManager.java
new file mode 100644
index 000000000..67798a683
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AIMDBackoffManager.java
@@ -0,0 +1,164 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.client.BackoffManager;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.pool.ConnPoolControl;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * <p>The <code>AIMDBackoffManager</code> applies an additive increase,
+ * multiplicative decrease (AIMD) to managing a dynamic limit to
+ * the number of connections allowed to a given host. You may want
+ * to experiment with the settings for the cooldown periods and the
+ * backoff factor to get the adaptive behavior you want.</p>
+ *
+ * <p>Generally speaking, shorter cooldowns will lead to more steady-state
+ * variability but faster reaction times, while longer cooldowns
+ * will lead to more stable equilibrium behavior but slower reaction
+ * times.</p>
+ *
+ * <p>Similarly, higher backoff factors promote greater
+ * utilization of available capacity at the expense of fairness
+ * among clients. Lower backoff factors allow equal distribution of
+ * capacity among clients (fairness) to happen faster, at the
+ * expense of having more server capacity unused in the short term.</p>
+ *
+ * @since 4.2
+ */
+public class AIMDBackoffManager implements BackoffManager {
+
+ private final ConnPoolControl<HttpRoute> connPerRoute;
+ private final Clock clock;
+ private final Map<HttpRoute,Long> lastRouteProbes;
+ private final Map<HttpRoute,Long> lastRouteBackoffs;
+ private long coolDown = 5 * 1000L;
+ private double backoffFactor = 0.5;
+ private int cap = 2; // Per RFC 2616 sec 8.1.4
+
+ /**
+ * Creates an <code>AIMDBackoffManager</code> to manage
+ * per-host connection pool sizes represented by the
+ * given {@link ConnPoolControl}.
+ * @param connPerRoute per-host routing maximums to
+ * be managed
+ */
+ public AIMDBackoffManager(final ConnPoolControl<HttpRoute> connPerRoute) {
+ this(connPerRoute, new SystemClock());
+ }
+
+ AIMDBackoffManager(final ConnPoolControl<HttpRoute> connPerRoute, final Clock clock) {
+ this.clock = clock;
+ this.connPerRoute = connPerRoute;
+ this.lastRouteProbes = new HashMap<HttpRoute,Long>();
+ this.lastRouteBackoffs = new HashMap<HttpRoute,Long>();
+ }
+
+ public void backOff(final HttpRoute route) {
+ synchronized(connPerRoute) {
+ final int curr = connPerRoute.getMaxPerRoute(route);
+ final Long lastUpdate = getLastUpdate(lastRouteBackoffs, route);
+ final long now = clock.getCurrentTime();
+ if (now - lastUpdate.longValue() < coolDown) {
+ return;
+ }
+ connPerRoute.setMaxPerRoute(route, getBackedOffPoolSize(curr));
+ lastRouteBackoffs.put(route, Long.valueOf(now));
+ }
+ }
+
+ private int getBackedOffPoolSize(final int curr) {
+ if (curr <= 1) {
+ return 1;
+ }
+ return (int)(Math.floor(backoffFactor * curr));
+ }
+
+ public void probe(final HttpRoute route) {
+ synchronized(connPerRoute) {
+ final int curr = connPerRoute.getMaxPerRoute(route);
+ final int max = (curr >= cap) ? cap : curr + 1;
+ final Long lastProbe = getLastUpdate(lastRouteProbes, route);
+ final Long lastBackoff = getLastUpdate(lastRouteBackoffs, route);
+ final long now = clock.getCurrentTime();
+ if (now - lastProbe.longValue() < coolDown || now - lastBackoff.longValue() < coolDown) {
+ return;
+ }
+ connPerRoute.setMaxPerRoute(route, max);
+ lastRouteProbes.put(route, Long.valueOf(now));
+ }
+ }
+
+ private Long getLastUpdate(final Map<HttpRoute,Long> updates, final HttpRoute route) {
+ Long lastUpdate = updates.get(route);
+ if (lastUpdate == null) {
+ lastUpdate = Long.valueOf(0L);
+ }
+ return lastUpdate;
+ }
+
+ /**
+ * Sets the factor to use when backing off; the new
+ * per-host limit will be roughly the current max times
+ * this factor. <code>Math.floor</code> is applied in the
+ * case of non-integer outcomes to ensure we actually
+ * decrease the pool size. Pool sizes are never decreased
+ * below 1, however. Defaults to 0.5.
+ * @param d must be between 0.0 and 1.0, exclusive.
+ */
+ public void setBackoffFactor(final double d) {
+ Args.check(d > 0.0 && d < 1.0, "Backoff factor must be 0.0 < f < 1.0");
+ backoffFactor = d;
+ }
+
+ /**
+ * Sets the amount of time, in milliseconds, to wait between
+ * adjustments in pool sizes for a given host, to allow
+ * enough time for the adjustments to take effect. Defaults
+ * to 5000L (5 seconds).
+ * @param l must be positive
+ */
+ public void setCooldownMillis(final long l) {
+ Args.positive(coolDown, "Cool down");
+ coolDown = l;
+ }
+
+ /**
+ * Sets the absolute maximum per-host connection pool size to
+ * probe up to; defaults to 2 (the default per-host max).
+ * @param cap must be >= 1
+ */
+ public void setPerHostConnectionCap(final int cap) {
+ Args.positive(cap, "Per host connection cap");
+ this.cap = cap;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java
new file mode 100644
index 000000000..a02c1a03b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java
@@ -0,0 +1,189 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.client.AuthenticationHandler;
+import ch.boye.httpclientandroidlib.client.params.AuthPolicy;
+import ch.boye.httpclientandroidlib.client.protocol.ClientContext;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Base class for {@link AuthenticationHandler} implementations.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.client.AuthenticationStrategy}
+ */
+@Deprecated
+@Immutable
+public abstract class AbstractAuthenticationHandler implements AuthenticationHandler {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private static final List<String> DEFAULT_SCHEME_PRIORITY =
+ Collections.unmodifiableList(Arrays.asList(new String[] {
+ AuthPolicy.SPNEGO,
+ AuthPolicy.NTLM,
+ AuthPolicy.DIGEST,
+ AuthPolicy.BASIC
+ }));
+
+ public AbstractAuthenticationHandler() {
+ super();
+ }
+
+ protected Map<String, Header> parseChallenges(
+ final Header[] headers) throws MalformedChallengeException {
+
+ final Map<String, Header> map = new HashMap<String, Header>(headers.length);
+ for (final Header header : headers) {
+ final CharArrayBuffer buffer;
+ int pos;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ pos = ((FormattedHeader) header).getValuePos();
+ } else {
+ final String s = header.getValue();
+ if (s == null) {
+ throw new MalformedChallengeException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ pos = 0;
+ }
+ while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ final int beginIndex = pos;
+ while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ final int endIndex = pos;
+ final String s = buffer.substring(beginIndex, endIndex);
+ map.put(s.toLowerCase(Locale.ENGLISH), header);
+ }
+ return map;
+ }
+
+ /**
+ * Returns default list of auth scheme names in their order of preference.
+ *
+ * @return list of auth scheme names
+ */
+ protected List<String> getAuthPreferences() {
+ return DEFAULT_SCHEME_PRIORITY;
+ }
+
+ /**
+ * Returns default list of auth scheme names in their order of preference
+ * based on the HTTP response and the current execution context.
+ *
+ * @param response HTTP response.
+ * @param context HTTP execution context.
+ *
+ * @since 4.1
+ */
+ protected List<String> getAuthPreferences(
+ final HttpResponse response,
+ final HttpContext context) {
+ return getAuthPreferences();
+ }
+
+ public AuthScheme selectScheme(
+ final Map<String, Header> challenges,
+ final HttpResponse response,
+ final HttpContext context) throws AuthenticationException {
+
+ final AuthSchemeRegistry registry = (AuthSchemeRegistry) context.getAttribute(
+ ClientContext.AUTHSCHEME_REGISTRY);
+ Asserts.notNull(registry, "AuthScheme registry");
+ Collection<String> authPrefs = getAuthPreferences(response, context);
+ if (authPrefs == null) {
+ authPrefs = DEFAULT_SCHEME_PRIORITY;
+ }
+
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Authentication schemes in the order of preference: "
+ + authPrefs);
+ }
+
+ AuthScheme authScheme = null;
+ for (final String id: authPrefs) {
+ final Header challenge = challenges.get(id.toLowerCase(Locale.ENGLISH));
+
+ if (challenge != null) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(id + " authentication scheme selected");
+ }
+ try {
+ authScheme = registry.getAuthScheme(id, response.getParams());
+ break;
+ } catch (final IllegalStateException e) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Authentication scheme " + id + " not supported");
+ // Try again
+ }
+ }
+ } else {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Challenge for " + id + " authentication scheme not available");
+ // Try again
+ }
+ }
+ }
+ if (authScheme == null) {
+ // If none selected, something is wrong
+ throw new AuthenticationException(
+ "Unable to respond to any of these challenges: "
+ + challenges);
+ }
+ return authScheme;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractHttpClient.java
new file mode 100644
index 000000000..f862c9886
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AbstractHttpClient.java
@@ -0,0 +1,990 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry;
+import ch.boye.httpclientandroidlib.client.AuthenticationHandler;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.client.BackoffManager;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.ConnectionBackoffStrategy;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler;
+import ch.boye.httpclientandroidlib.client.RedirectHandler;
+import ch.boye.httpclientandroidlib.client.RedirectStrategy;
+import ch.boye.httpclientandroidlib.client.RequestDirector;
+import ch.boye.httpclientandroidlib.client.UserTokenHandler;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.params.AuthPolicy;
+import ch.boye.httpclientandroidlib.client.params.ClientPNames;
+import ch.boye.httpclientandroidlib.client.params.CookiePolicy;
+import ch.boye.httpclientandroidlib.client.params.HttpClientParamConfig;
+import ch.boye.httpclientandroidlib.client.protocol.ClientContext;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManagerFactory;
+import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecRegistry;
+import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.auth.BasicSchemeFactory;
+import ch.boye.httpclientandroidlib.impl.auth.DigestSchemeFactory;
+/* KerberosSchemeFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.impl.auth.NTLMSchemeFactory;
+/* SPNegoSchemeFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.impl.conn.BasicClientConnectionManager;
+import ch.boye.httpclientandroidlib.impl.conn.DefaultHttpRoutePlanner;
+import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.BestMatchSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.BrowserCompatSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.IgnoreSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.NetscapeDraftSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.RFC2109SpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.RFC2965SpecFactory;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.DefaultedHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor;
+import ch.boye.httpclientandroidlib.protocol.ImmutableHttpProcessor;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Base class for {@link ch.boye.httpclientandroidlib.client.HttpClient} implementations.
+ * This class acts as a facade to a number of special purpose handler or
+ * strategy implementations responsible for handling of a particular aspect
+ * of the HTTP protocol such as redirect or authentication handling or
+ * making decision about connection persistence and keep alive duration.
+ * This enables the users to selectively replace default implementation
+ * of those aspects with custom, application specific ones. This class
+ * also provides factory methods to instantiate those objects:
+ * <ul>
+ * <li>{@link HttpRequestExecutor}</li> object used to transmit messages
+ * over HTTP connections. The {@link #createRequestExecutor()} must be
+ * implemented by concrete super classes to instantiate this object.
+ * <li>{@link BasicHttpProcessor}</li> object to manage a list of protocol
+ * interceptors and apply cross-cutting protocol logic to all incoming
+ * and outgoing HTTP messages. The {@link #createHttpProcessor()} must be
+ * implemented by concrete super classes to instantiate this object.
+ * <li>{@link HttpRequestRetryHandler}</li> object used to decide whether
+ * or not a failed HTTP request is safe to retry automatically.
+ * The {@link #createHttpRequestRetryHandler()} must be
+ * implemented by concrete super classes to instantiate this object.
+ * <li>{@link ClientConnectionManager}</li> object used to manage
+ * persistent HTTP connections.
+ * <li>{@link ConnectionReuseStrategy}</li> object used to decide whether
+ * or not a HTTP connection can be kept alive and re-used for subsequent
+ * HTTP requests. The {@link #createConnectionReuseStrategy()} must be
+ * implemented by concrete super classes to instantiate this object.
+ * <li>{@link ConnectionKeepAliveStrategy}</li> object used to decide how
+ * long a persistent HTTP connection can be kept alive.
+ * The {@link #createConnectionKeepAliveStrategy()} must be
+ * implemented by concrete super classes to instantiate this object.
+ * <li>{@link CookieSpecRegistry}</li> object used to maintain a list of
+ * supported cookie specifications.
+ * The {@link #createCookieSpecRegistry()} must be implemented by concrete
+ * super classes to instantiate this object.
+ * <li>{@link CookieStore}</li> object used to maintain a collection of
+ * cookies. The {@link #createCookieStore()} must be implemented by
+ * concrete super classes to instantiate this object.
+ * <li>{@link AuthSchemeRegistry}</li> object used to maintain a list of
+ * supported authentication schemes.
+ * The {@link #createAuthSchemeRegistry()} must be implemented by concrete
+ * super classes to instantiate this object.
+ * <li>{@link CredentialsProvider}</li> object used to maintain
+ * a collection user credentials. The {@link #createCredentialsProvider()}
+ * must be implemented by concrete super classes to instantiate
+ * this object.
+ * <li>{@link AuthenticationStrategy}</li> object used to authenticate
+ * against the target host.
+ * The {@link #createTargetAuthenticationStrategy()} must be implemented
+ * by concrete super classes to instantiate this object.
+ * <li>{@link AuthenticationStrategy}</li> object used to authenticate
+ * against the proxy host.
+ * The {@link #createProxyAuthenticationStrategy()} must be implemented
+ * by concrete super classes to instantiate this object.
+ * <li>{@link HttpRoutePlanner}</li> object used to calculate a route
+ * for establishing a connection to the target host. The route
+ * may involve multiple intermediate hops.
+ * The {@link #createHttpRoutePlanner()} must be implemented
+ * by concrete super classes to instantiate this object.
+ * <li>{@link RedirectStrategy}</li> object used to determine if an HTTP
+ * request should be redirected to a new location in response to an HTTP
+ * response received from the target server.
+ * <li>{@link UserTokenHandler}</li> object used to determine if the
+ * execution context is user identity specific.
+ * The {@link #createUserTokenHandler()} must be implemented by
+ * concrete super classes to instantiate this object.
+ * </ul>
+ * <p>
+ * This class also maintains a list of protocol interceptors intended
+ * for processing outgoing requests and incoming responses and provides
+ * methods for managing those interceptors. New protocol interceptors can be
+ * introduced to the protocol processor chain or removed from it if needed.
+ * Internally protocol interceptors are stored in a simple
+ * {@link java.util.ArrayList}. They are executed in the same natural order
+ * as they are added to the list.
+ * <p>
+ * AbstractHttpClient is thread safe. It is recommended that the same
+ * instance of this class is reused for multiple request executions.
+ * When an instance of DefaultHttpClient is no longer needed and is about
+ * to go out of scope the connection manager associated with it must be
+ * shut down by calling {@link ClientConnectionManager#shutdown()}!
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link HttpClientBuilder}.
+ */
+@ThreadSafe
+@Deprecated
+public abstract class AbstractHttpClient extends CloseableHttpClient {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /** The parameters. */
+ @GuardedBy("this")
+ private HttpParams defaultParams;
+
+ /** The request executor. */
+ @GuardedBy("this")
+ private HttpRequestExecutor requestExec;
+
+ /** The connection manager. */
+ @GuardedBy("this")
+ private ClientConnectionManager connManager;
+
+ /** The connection re-use strategy. */
+ @GuardedBy("this")
+ private ConnectionReuseStrategy reuseStrategy;
+
+ /** The connection keep-alive strategy. */
+ @GuardedBy("this")
+ private ConnectionKeepAliveStrategy keepAliveStrategy;
+
+ /** The cookie spec registry. */
+ @GuardedBy("this")
+ private CookieSpecRegistry supportedCookieSpecs;
+
+ /** The authentication scheme registry. */
+ @GuardedBy("this")
+ private AuthSchemeRegistry supportedAuthSchemes;
+
+ /** The HTTP protocol processor and its immutable copy. */
+ @GuardedBy("this")
+ private BasicHttpProcessor mutableProcessor;
+
+ @GuardedBy("this")
+ private ImmutableHttpProcessor protocolProcessor;
+
+ /** The request retry handler. */
+ @GuardedBy("this")
+ private HttpRequestRetryHandler retryHandler;
+
+ /** The redirect handler. */
+ @GuardedBy("this")
+ private RedirectStrategy redirectStrategy;
+
+ /** The target authentication handler. */
+ @GuardedBy("this")
+ private AuthenticationStrategy targetAuthStrategy;
+
+ /** The proxy authentication handler. */
+ @GuardedBy("this")
+ private AuthenticationStrategy proxyAuthStrategy;
+
+ /** The cookie store. */
+ @GuardedBy("this")
+ private CookieStore cookieStore;
+
+ /** The credentials provider. */
+ @GuardedBy("this")
+ private CredentialsProvider credsProvider;
+
+ /** The route planner. */
+ @GuardedBy("this")
+ private HttpRoutePlanner routePlanner;
+
+ /** The user token handler. */
+ @GuardedBy("this")
+ private UserTokenHandler userTokenHandler;
+
+ /** The connection backoff strategy. */
+ @GuardedBy("this")
+ private ConnectionBackoffStrategy connectionBackoffStrategy;
+
+ /** The backoff manager. */
+ @GuardedBy("this")
+ private BackoffManager backoffManager;
+
+ /**
+ * Creates a new HTTP client.
+ *
+ * @param conman the connection manager
+ * @param params the parameters
+ */
+ protected AbstractHttpClient(
+ final ClientConnectionManager conman,
+ final HttpParams params) {
+ super();
+ defaultParams = params;
+ connManager = conman;
+ } // constructor
+
+
+ protected abstract HttpParams createHttpParams();
+
+
+ protected abstract BasicHttpProcessor createHttpProcessor();
+
+
+ protected HttpContext createHttpContext() {
+ final HttpContext context = new BasicHttpContext();
+ context.setAttribute(
+ ClientContext.SCHEME_REGISTRY,
+ getConnectionManager().getSchemeRegistry());
+ context.setAttribute(
+ ClientContext.AUTHSCHEME_REGISTRY,
+ getAuthSchemes());
+ context.setAttribute(
+ ClientContext.COOKIESPEC_REGISTRY,
+ getCookieSpecs());
+ context.setAttribute(
+ ClientContext.COOKIE_STORE,
+ getCookieStore());
+ context.setAttribute(
+ ClientContext.CREDS_PROVIDER,
+ getCredentialsProvider());
+ return context;
+ }
+
+
+ protected ClientConnectionManager createClientConnectionManager() {
+ final SchemeRegistry registry = SchemeRegistryFactory.createDefault();
+
+ ClientConnectionManager connManager = null;
+ final HttpParams params = getParams();
+
+ ClientConnectionManagerFactory factory = null;
+
+ final String className = (String) params.getParameter(
+ ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME);
+ if (className != null) {
+ try {
+ final Class<?> clazz = Class.forName(className);
+ factory = (ClientConnectionManagerFactory) clazz.newInstance();
+ } catch (final ClassNotFoundException ex) {
+ throw new IllegalStateException("Invalid class name: " + className);
+ } catch (final IllegalAccessException ex) {
+ throw new IllegalAccessError(ex.getMessage());
+ } catch (final InstantiationException ex) {
+ throw new InstantiationError(ex.getMessage());
+ }
+ }
+ if (factory != null) {
+ connManager = factory.newInstance(params, registry);
+ } else {
+ connManager = new BasicClientConnectionManager(registry);
+ }
+
+ return connManager;
+ }
+
+
+ protected AuthSchemeRegistry createAuthSchemeRegistry() {
+ final AuthSchemeRegistry registry = new AuthSchemeRegistry();
+ registry.register(
+ AuthPolicy.BASIC,
+ new BasicSchemeFactory());
+ registry.register(
+ AuthPolicy.DIGEST,
+ new DigestSchemeFactory());
+ registry.register(
+ AuthPolicy.NTLM,
+ new NTLMSchemeFactory());
+ /* SPNegoSchemeFactory removed by HttpClient for Android script. */
+ /* KerberosSchemeFactory removed by HttpClient for Android script. */
+ return registry;
+ }
+
+
+ protected CookieSpecRegistry createCookieSpecRegistry() {
+ final CookieSpecRegistry registry = new CookieSpecRegistry();
+ registry.register(
+ CookiePolicy.BEST_MATCH,
+ new BestMatchSpecFactory());
+ registry.register(
+ CookiePolicy.BROWSER_COMPATIBILITY,
+ new BrowserCompatSpecFactory());
+ registry.register(
+ CookiePolicy.NETSCAPE,
+ new NetscapeDraftSpecFactory());
+ registry.register(
+ CookiePolicy.RFC_2109,
+ new RFC2109SpecFactory());
+ registry.register(
+ CookiePolicy.RFC_2965,
+ new RFC2965SpecFactory());
+ registry.register(
+ CookiePolicy.IGNORE_COOKIES,
+ new IgnoreSpecFactory());
+ return registry;
+ }
+
+ protected HttpRequestExecutor createRequestExecutor() {
+ return new HttpRequestExecutor();
+ }
+
+ protected ConnectionReuseStrategy createConnectionReuseStrategy() {
+ return new DefaultConnectionReuseStrategy();
+ }
+
+ protected ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy() {
+ return new DefaultConnectionKeepAliveStrategy();
+ }
+
+ protected HttpRequestRetryHandler createHttpRequestRetryHandler() {
+ return new DefaultHttpRequestRetryHandler();
+ }
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ protected RedirectHandler createRedirectHandler() {
+ return new DefaultRedirectHandler();
+ }
+
+ protected AuthenticationStrategy createTargetAuthenticationStrategy() {
+ return new TargetAuthenticationStrategy();
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ protected AuthenticationHandler createTargetAuthenticationHandler() {
+ return new DefaultTargetAuthenticationHandler();
+ }
+
+ protected AuthenticationStrategy createProxyAuthenticationStrategy() {
+ return new ProxyAuthenticationStrategy();
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ protected AuthenticationHandler createProxyAuthenticationHandler() {
+ return new DefaultProxyAuthenticationHandler();
+ }
+
+ protected CookieStore createCookieStore() {
+ return new BasicCookieStore();
+ }
+
+ protected CredentialsProvider createCredentialsProvider() {
+ return new BasicCredentialsProvider();
+ }
+
+ protected HttpRoutePlanner createHttpRoutePlanner() {
+ return new DefaultHttpRoutePlanner(getConnectionManager().getSchemeRegistry());
+ }
+
+ protected UserTokenHandler createUserTokenHandler() {
+ return new DefaultUserTokenHandler();
+ }
+
+ // non-javadoc, see interface HttpClient
+ public synchronized final HttpParams getParams() {
+ if (defaultParams == null) {
+ defaultParams = createHttpParams();
+ }
+ return defaultParams;
+ }
+
+ /**
+ * Replaces the parameters.
+ * The implementation here does not update parameters of dependent objects.
+ *
+ * @param params the new default parameters
+ */
+ public synchronized void setParams(final HttpParams params) {
+ defaultParams = params;
+ }
+
+
+ public synchronized final ClientConnectionManager getConnectionManager() {
+ if (connManager == null) {
+ connManager = createClientConnectionManager();
+ }
+ return connManager;
+ }
+
+
+ public synchronized final HttpRequestExecutor getRequestExecutor() {
+ if (requestExec == null) {
+ requestExec = createRequestExecutor();
+ }
+ return requestExec;
+ }
+
+
+ public synchronized final AuthSchemeRegistry getAuthSchemes() {
+ if (supportedAuthSchemes == null) {
+ supportedAuthSchemes = createAuthSchemeRegistry();
+ }
+ return supportedAuthSchemes;
+ }
+
+ public synchronized void setAuthSchemes(final AuthSchemeRegistry registry) {
+ supportedAuthSchemes = registry;
+ }
+
+ public synchronized final ConnectionBackoffStrategy getConnectionBackoffStrategy() {
+ return connectionBackoffStrategy;
+ }
+
+ public synchronized void setConnectionBackoffStrategy(final ConnectionBackoffStrategy strategy) {
+ connectionBackoffStrategy = strategy;
+ }
+
+ public synchronized final CookieSpecRegistry getCookieSpecs() {
+ if (supportedCookieSpecs == null) {
+ supportedCookieSpecs = createCookieSpecRegistry();
+ }
+ return supportedCookieSpecs;
+ }
+
+ public synchronized final BackoffManager getBackoffManager() {
+ return backoffManager;
+ }
+
+ public synchronized void setBackoffManager(final BackoffManager manager) {
+ backoffManager = manager;
+ }
+
+ public synchronized void setCookieSpecs(final CookieSpecRegistry registry) {
+ supportedCookieSpecs = registry;
+ }
+
+ public synchronized final ConnectionReuseStrategy getConnectionReuseStrategy() {
+ if (reuseStrategy == null) {
+ reuseStrategy = createConnectionReuseStrategy();
+ }
+ return reuseStrategy;
+ }
+
+
+ public synchronized void setReuseStrategy(final ConnectionReuseStrategy strategy) {
+ this.reuseStrategy = strategy;
+ }
+
+
+ public synchronized final ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() {
+ if (keepAliveStrategy == null) {
+ keepAliveStrategy = createConnectionKeepAliveStrategy();
+ }
+ return keepAliveStrategy;
+ }
+
+
+ public synchronized void setKeepAliveStrategy(final ConnectionKeepAliveStrategy strategy) {
+ this.keepAliveStrategy = strategy;
+ }
+
+
+ public synchronized final HttpRequestRetryHandler getHttpRequestRetryHandler() {
+ if (retryHandler == null) {
+ retryHandler = createHttpRequestRetryHandler();
+ }
+ return retryHandler;
+ }
+
+ public synchronized void setHttpRequestRetryHandler(final HttpRequestRetryHandler handler) {
+ this.retryHandler = handler;
+ }
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ public synchronized final RedirectHandler getRedirectHandler() {
+ return createRedirectHandler();
+ }
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ public synchronized void setRedirectHandler(final RedirectHandler handler) {
+ this.redirectStrategy = new DefaultRedirectStrategyAdaptor(handler);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public synchronized final RedirectStrategy getRedirectStrategy() {
+ if (redirectStrategy == null) {
+ redirectStrategy = new DefaultRedirectStrategy();
+ }
+ return redirectStrategy;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public synchronized void setRedirectStrategy(final RedirectStrategy strategy) {
+ this.redirectStrategy = strategy;
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ public synchronized final AuthenticationHandler getTargetAuthenticationHandler() {
+ return createTargetAuthenticationHandler();
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ public synchronized void setTargetAuthenticationHandler(final AuthenticationHandler handler) {
+ this.targetAuthStrategy = new AuthenticationStrategyAdaptor(handler);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public synchronized final AuthenticationStrategy getTargetAuthenticationStrategy() {
+ if (targetAuthStrategy == null) {
+ targetAuthStrategy = createTargetAuthenticationStrategy();
+ }
+ return targetAuthStrategy;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public synchronized void setTargetAuthenticationStrategy(final AuthenticationStrategy strategy) {
+ this.targetAuthStrategy = strategy;
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ public synchronized final AuthenticationHandler getProxyAuthenticationHandler() {
+ return createProxyAuthenticationHandler();
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ public synchronized void setProxyAuthenticationHandler(final AuthenticationHandler handler) {
+ this.proxyAuthStrategy = new AuthenticationStrategyAdaptor(handler);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public synchronized final AuthenticationStrategy getProxyAuthenticationStrategy() {
+ if (proxyAuthStrategy == null) {
+ proxyAuthStrategy = createProxyAuthenticationStrategy();
+ }
+ return proxyAuthStrategy;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public synchronized void setProxyAuthenticationStrategy(final AuthenticationStrategy strategy) {
+ this.proxyAuthStrategy = strategy;
+ }
+
+ public synchronized final CookieStore getCookieStore() {
+ if (cookieStore == null) {
+ cookieStore = createCookieStore();
+ }
+ return cookieStore;
+ }
+
+ public synchronized void setCookieStore(final CookieStore cookieStore) {
+ this.cookieStore = cookieStore;
+ }
+
+ public synchronized final CredentialsProvider getCredentialsProvider() {
+ if (credsProvider == null) {
+ credsProvider = createCredentialsProvider();
+ }
+ return credsProvider;
+ }
+
+ public synchronized void setCredentialsProvider(final CredentialsProvider credsProvider) {
+ this.credsProvider = credsProvider;
+ }
+
+ public synchronized final HttpRoutePlanner getRoutePlanner() {
+ if (this.routePlanner == null) {
+ this.routePlanner = createHttpRoutePlanner();
+ }
+ return this.routePlanner;
+ }
+
+ public synchronized void setRoutePlanner(final HttpRoutePlanner routePlanner) {
+ this.routePlanner = routePlanner;
+ }
+
+ public synchronized final UserTokenHandler getUserTokenHandler() {
+ if (this.userTokenHandler == null) {
+ this.userTokenHandler = createUserTokenHandler();
+ }
+ return this.userTokenHandler;
+ }
+
+ public synchronized void setUserTokenHandler(final UserTokenHandler handler) {
+ this.userTokenHandler = handler;
+ }
+
+ protected synchronized final BasicHttpProcessor getHttpProcessor() {
+ if (mutableProcessor == null) {
+ mutableProcessor = createHttpProcessor();
+ }
+ return mutableProcessor;
+ }
+
+ private synchronized HttpProcessor getProtocolProcessor() {
+ if (protocolProcessor == null) {
+ // Get mutable HTTP processor
+ final BasicHttpProcessor proc = getHttpProcessor();
+ // and create an immutable copy of it
+ final int reqc = proc.getRequestInterceptorCount();
+ final HttpRequestInterceptor[] reqinterceptors = new HttpRequestInterceptor[reqc];
+ for (int i = 0; i < reqc; i++) {
+ reqinterceptors[i] = proc.getRequestInterceptor(i);
+ }
+ final int resc = proc.getResponseInterceptorCount();
+ final HttpResponseInterceptor[] resinterceptors = new HttpResponseInterceptor[resc];
+ for (int i = 0; i < resc; i++) {
+ resinterceptors[i] = proc.getResponseInterceptor(i);
+ }
+ protocolProcessor = new ImmutableHttpProcessor(reqinterceptors, resinterceptors);
+ }
+ return protocolProcessor;
+ }
+
+ public synchronized int getResponseInterceptorCount() {
+ return getHttpProcessor().getResponseInterceptorCount();
+ }
+
+ public synchronized HttpResponseInterceptor getResponseInterceptor(final int index) {
+ return getHttpProcessor().getResponseInterceptor(index);
+ }
+
+ public synchronized HttpRequestInterceptor getRequestInterceptor(final int index) {
+ return getHttpProcessor().getRequestInterceptor(index);
+ }
+
+ public synchronized int getRequestInterceptorCount() {
+ return getHttpProcessor().getRequestInterceptorCount();
+ }
+
+ public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp) {
+ getHttpProcessor().addInterceptor(itcp);
+ protocolProcessor = null;
+ }
+
+ public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp, final int index) {
+ getHttpProcessor().addInterceptor(itcp, index);
+ protocolProcessor = null;
+ }
+
+ public synchronized void clearResponseInterceptors() {
+ getHttpProcessor().clearResponseInterceptors();
+ protocolProcessor = null;
+ }
+
+ public synchronized void removeResponseInterceptorByClass(final Class<? extends HttpResponseInterceptor> clazz) {
+ getHttpProcessor().removeResponseInterceptorByClass(clazz);
+ protocolProcessor = null;
+ }
+
+ public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp) {
+ getHttpProcessor().addInterceptor(itcp);
+ protocolProcessor = null;
+ }
+
+ public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp, final int index) {
+ getHttpProcessor().addInterceptor(itcp, index);
+ protocolProcessor = null;
+ }
+
+ public synchronized void clearRequestInterceptors() {
+ getHttpProcessor().clearRequestInterceptors();
+ protocolProcessor = null;
+ }
+
+ public synchronized void removeRequestInterceptorByClass(final Class<? extends HttpRequestInterceptor> clazz) {
+ getHttpProcessor().removeRequestInterceptorByClass(clazz);
+ protocolProcessor = null;
+ }
+
+ @Override
+ protected final CloseableHttpResponse doExecute(final HttpHost target, final HttpRequest request,
+ final HttpContext context)
+ throws IOException, ClientProtocolException {
+
+ Args.notNull(request, "HTTP request");
+ // a null target may be acceptable, this depends on the route planner
+ // a null context is acceptable, default context created below
+
+ HttpContext execContext = null;
+ RequestDirector director = null;
+ HttpRoutePlanner routePlanner = null;
+ ConnectionBackoffStrategy connectionBackoffStrategy = null;
+ BackoffManager backoffManager = null;
+
+ // Initialize the request execution context making copies of
+ // all shared objects that are potentially threading unsafe.
+ synchronized (this) {
+
+ final HttpContext defaultContext = createHttpContext();
+ if (context == null) {
+ execContext = defaultContext;
+ } else {
+ execContext = new DefaultedHttpContext(context, defaultContext);
+ }
+ final HttpParams params = determineParams(request);
+ final RequestConfig config = HttpClientParamConfig.getRequestConfig(params);
+ execContext.setAttribute(ClientContext.REQUEST_CONFIG, config);
+
+ // Create a director for this request
+ director = createClientRequestDirector(
+ getRequestExecutor(),
+ getConnectionManager(),
+ getConnectionReuseStrategy(),
+ getConnectionKeepAliveStrategy(),
+ getRoutePlanner(),
+ getProtocolProcessor(),
+ getHttpRequestRetryHandler(),
+ getRedirectStrategy(),
+ getTargetAuthenticationStrategy(),
+ getProxyAuthenticationStrategy(),
+ getUserTokenHandler(),
+ params);
+ routePlanner = getRoutePlanner();
+ connectionBackoffStrategy = getConnectionBackoffStrategy();
+ backoffManager = getBackoffManager();
+ }
+
+ try {
+ if (connectionBackoffStrategy != null && backoffManager != null) {
+ final HttpHost targetForRoute = (target != null) ? target
+ : (HttpHost) determineParams(request).getParameter(
+ ClientPNames.DEFAULT_HOST);
+ final HttpRoute route = routePlanner.determineRoute(targetForRoute, request, execContext);
+
+ final CloseableHttpResponse out;
+ try {
+ out = CloseableHttpResponseProxy.newProxy(
+ director.execute(target, request, execContext));
+ } catch (final RuntimeException re) {
+ if (connectionBackoffStrategy.shouldBackoff(re)) {
+ backoffManager.backOff(route);
+ }
+ throw re;
+ } catch (final Exception e) {
+ if (connectionBackoffStrategy.shouldBackoff(e)) {
+ backoffManager.backOff(route);
+ }
+ if (e instanceof HttpException) {
+ throw (HttpException)e;
+ }
+ if (e instanceof IOException) {
+ throw (IOException)e;
+ }
+ throw new UndeclaredThrowableException(e);
+ }
+ if (connectionBackoffStrategy.shouldBackoff(out)) {
+ backoffManager.backOff(route);
+ } else {
+ backoffManager.probe(route);
+ }
+ return out;
+ } else {
+ return CloseableHttpResponseProxy.newProxy(
+ director.execute(target, request, execContext));
+ }
+ } catch(final HttpException httpException) {
+ throw new ClientProtocolException(httpException);
+ }
+ }
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ protected RequestDirector createClientRequestDirector(
+ final HttpRequestExecutor requestExec,
+ final ClientConnectionManager conman,
+ final ConnectionReuseStrategy reustrat,
+ final ConnectionKeepAliveStrategy kastrat,
+ final HttpRoutePlanner rouplan,
+ final HttpProcessor httpProcessor,
+ final HttpRequestRetryHandler retryHandler,
+ final RedirectHandler redirectHandler,
+ final AuthenticationHandler targetAuthHandler,
+ final AuthenticationHandler proxyAuthHandler,
+ final UserTokenHandler userTokenHandler,
+ final HttpParams params) {
+ return new DefaultRequestDirector(
+ requestExec,
+ conman,
+ reustrat,
+ kastrat,
+ rouplan,
+ httpProcessor,
+ retryHandler,
+ redirectHandler,
+ targetAuthHandler,
+ proxyAuthHandler,
+ userTokenHandler,
+ params);
+ }
+
+ /**
+ * @deprecated (4.2) do not use
+ */
+ @Deprecated
+ protected RequestDirector createClientRequestDirector(
+ final HttpRequestExecutor requestExec,
+ final ClientConnectionManager conman,
+ final ConnectionReuseStrategy reustrat,
+ final ConnectionKeepAliveStrategy kastrat,
+ final HttpRoutePlanner rouplan,
+ final HttpProcessor httpProcessor,
+ final HttpRequestRetryHandler retryHandler,
+ final RedirectStrategy redirectStrategy,
+ final AuthenticationHandler targetAuthHandler,
+ final AuthenticationHandler proxyAuthHandler,
+ final UserTokenHandler userTokenHandler,
+ final HttpParams params) {
+ return new DefaultRequestDirector(
+ log,
+ requestExec,
+ conman,
+ reustrat,
+ kastrat,
+ rouplan,
+ httpProcessor,
+ retryHandler,
+ redirectStrategy,
+ targetAuthHandler,
+ proxyAuthHandler,
+ userTokenHandler,
+ params);
+ }
+
+
+ /**
+ * @since 4.2
+ */
+ protected RequestDirector createClientRequestDirector(
+ final HttpRequestExecutor requestExec,
+ final ClientConnectionManager conman,
+ final ConnectionReuseStrategy reustrat,
+ final ConnectionKeepAliveStrategy kastrat,
+ final HttpRoutePlanner rouplan,
+ final HttpProcessor httpProcessor,
+ final HttpRequestRetryHandler retryHandler,
+ final RedirectStrategy redirectStrategy,
+ final AuthenticationStrategy targetAuthStrategy,
+ final AuthenticationStrategy proxyAuthStrategy,
+ final UserTokenHandler userTokenHandler,
+ final HttpParams params) {
+ return new DefaultRequestDirector(
+ log,
+ requestExec,
+ conman,
+ reustrat,
+ kastrat,
+ rouplan,
+ httpProcessor,
+ retryHandler,
+ redirectStrategy,
+ targetAuthStrategy,
+ proxyAuthStrategy,
+ userTokenHandler,
+ params);
+ }
+
+ /**
+ * Obtains parameters for executing a request.
+ * The default implementation in this class creates a new
+ * {@link ClientParamsStack} from the request parameters
+ * and the client parameters.
+ * <br/>
+ * This method is called by the default implementation of
+ * {@link #execute(HttpHost,HttpRequest,HttpContext)}
+ * to obtain the parameters for the
+ * {@link DefaultRequestDirector}.
+ *
+ * @param req the request that will be executed
+ *
+ * @return the parameters to use
+ */
+ protected HttpParams determineParams(final HttpRequest req) {
+ return new ClientParamsStack
+ (null, getParams(), req.getParams(), null);
+ }
+
+
+ public void close() {
+ getConnectionManager().shutdown();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyAdaptor.java
new file mode 100644
index 000000000..a65ce7e95
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyAdaptor.java
@@ -0,0 +1,172 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Queue;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthOption;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.AuthenticationException;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.client.AuthCache;
+import ch.boye.httpclientandroidlib.client.AuthenticationHandler;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.params.AuthPolicy;
+import ch.boye.httpclientandroidlib.client.protocol.ClientContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * @deprecated (4.2) do not use
+ */
+@Immutable
+@Deprecated
+class AuthenticationStrategyAdaptor implements AuthenticationStrategy {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final AuthenticationHandler handler;
+
+ public AuthenticationStrategyAdaptor(final AuthenticationHandler handler) {
+ super();
+ this.handler = handler;
+ }
+
+ public boolean isAuthenticationRequested(
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) {
+ return this.handler.isAuthenticationRequested(response, context);
+ }
+
+ public Map<String, Header> getChallenges(
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ return this.handler.getChallenges(response, context);
+ }
+
+ public Queue<AuthOption> select(
+ final Map<String, Header> challenges,
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ Args.notNull(challenges, "Map of auth challenges");
+ Args.notNull(authhost, "Host");
+ Args.notNull(response, "HTTP response");
+ Args.notNull(context, "HTTP context");
+
+ final Queue<AuthOption> options = new LinkedList<AuthOption>();
+ final CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
+ ClientContext.CREDS_PROVIDER);
+ if (credsProvider == null) {
+ this.log.debug("Credentials provider not set in the context");
+ return options;
+ }
+
+ final AuthScheme authScheme;
+ try {
+ authScheme = this.handler.selectScheme(challenges, response, context);
+ } catch (final AuthenticationException ex) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn(ex.getMessage(), ex);
+ }
+ return options;
+ }
+ final String id = authScheme.getSchemeName();
+ final Header challenge = challenges.get(id.toLowerCase(Locale.ENGLISH));
+ authScheme.processChallenge(challenge);
+
+ final AuthScope authScope = new AuthScope(
+ authhost.getHostName(),
+ authhost.getPort(),
+ authScheme.getRealm(),
+ authScheme.getSchemeName());
+
+ final Credentials credentials = credsProvider.getCredentials(authScope);
+ if (credentials != null) {
+ options.add(new AuthOption(authScheme, credentials));
+ }
+ return options;
+ }
+
+ public void authSucceeded(
+ final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
+ AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
+ if (isCachable(authScheme)) {
+ if (authCache == null) {
+ authCache = new BasicAuthCache();
+ context.setAttribute(ClientContext.AUTH_CACHE, authCache);
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Caching '" + authScheme.getSchemeName() +
+ "' auth scheme for " + authhost);
+ }
+ authCache.put(authhost, authScheme);
+ }
+ }
+
+ public void authFailed(
+ final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
+ final AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
+ if (authCache == null) {
+ return;
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Removing from cache '" + authScheme.getSchemeName() +
+ "' auth scheme for " + authhost);
+ }
+ authCache.remove(authhost);
+ }
+
+ private boolean isCachable(final AuthScheme authScheme) {
+ if (authScheme == null || !authScheme.isComplete()) {
+ return false;
+ }
+ final String schemeName = authScheme.getSchemeName();
+ return schemeName.equalsIgnoreCase(AuthPolicy.BASIC) ||
+ schemeName.equalsIgnoreCase(AuthPolicy.DIGEST);
+ }
+
+ public AuthenticationHandler getHandler() {
+ return this.handler;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyImpl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyImpl.java
new file mode 100644
index 000000000..38b7df6d2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AuthenticationStrategyImpl.java
@@ -0,0 +1,245 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Queue;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthOption;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.client.AuthCache;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.config.AuthSchemes;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+@Immutable
+abstract class AuthenticationStrategyImpl implements AuthenticationStrategy {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private static final List<String> DEFAULT_SCHEME_PRIORITY =
+ Collections.unmodifiableList(Arrays.asList(AuthSchemes.SPNEGO,
+ AuthSchemes.KERBEROS,
+ AuthSchemes.NTLM,
+ AuthSchemes.DIGEST,
+ AuthSchemes.BASIC));
+
+ private final int challengeCode;
+ private final String headerName;
+
+ AuthenticationStrategyImpl(final int challengeCode, final String headerName) {
+ super();
+ this.challengeCode = challengeCode;
+ this.headerName = headerName;
+ }
+
+ public boolean isAuthenticationRequested(
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) {
+ Args.notNull(response, "HTTP response");
+ final int status = response.getStatusLine().getStatusCode();
+ return status == this.challengeCode;
+ }
+
+ public Map<String, Header> getChallenges(
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ Args.notNull(response, "HTTP response");
+ final Header[] headers = response.getHeaders(this.headerName);
+ final Map<String, Header> map = new HashMap<String, Header>(headers.length);
+ for (final Header header : headers) {
+ final CharArrayBuffer buffer;
+ int pos;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ pos = ((FormattedHeader) header).getValuePos();
+ } else {
+ final String s = header.getValue();
+ if (s == null) {
+ throw new MalformedChallengeException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ pos = 0;
+ }
+ while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ final int beginIndex = pos;
+ while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ final int endIndex = pos;
+ final String s = buffer.substring(beginIndex, endIndex);
+ map.put(s.toLowerCase(Locale.ENGLISH), header);
+ }
+ return map;
+ }
+
+ abstract Collection<String> getPreferredAuthSchemes(RequestConfig config);
+
+ public Queue<AuthOption> select(
+ final Map<String, Header> challenges,
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ Args.notNull(challenges, "Map of auth challenges");
+ Args.notNull(authhost, "Host");
+ Args.notNull(response, "HTTP response");
+ Args.notNull(context, "HTTP context");
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ final Queue<AuthOption> options = new LinkedList<AuthOption>();
+ final Lookup<AuthSchemeProvider> registry = clientContext.getAuthSchemeRegistry();
+ if (registry == null) {
+ this.log.debug("Auth scheme registry not set in the context");
+ return options;
+ }
+ final CredentialsProvider credsProvider = clientContext.getCredentialsProvider();
+ if (credsProvider == null) {
+ this.log.debug("Credentials provider not set in the context");
+ return options;
+ }
+ final RequestConfig config = clientContext.getRequestConfig();
+ Collection<String> authPrefs = getPreferredAuthSchemes(config);
+ if (authPrefs == null) {
+ authPrefs = DEFAULT_SCHEME_PRIORITY;
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Authentication schemes in the order of preference: " + authPrefs);
+ }
+
+ for (final String id: authPrefs) {
+ final Header challenge = challenges.get(id.toLowerCase(Locale.ENGLISH));
+ if (challenge != null) {
+ final AuthSchemeProvider authSchemeProvider = registry.lookup(id);
+ if (authSchemeProvider == null) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Authentication scheme " + id + " not supported");
+ // Try again
+ }
+ continue;
+ }
+ final AuthScheme authScheme = authSchemeProvider.create(context);
+ authScheme.processChallenge(challenge);
+
+ final AuthScope authScope = new AuthScope(
+ authhost.getHostName(),
+ authhost.getPort(),
+ authScheme.getRealm(),
+ authScheme.getSchemeName());
+
+ final Credentials credentials = credsProvider.getCredentials(authScope);
+ if (credentials != null) {
+ options.add(new AuthOption(authScheme, credentials));
+ }
+ } else {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Challenge for " + id + " authentication scheme not available");
+ // Try again
+ }
+ }
+ }
+ return options;
+ }
+
+ public void authSucceeded(
+ final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
+ Args.notNull(authhost, "Host");
+ Args.notNull(authScheme, "Auth scheme");
+ Args.notNull(context, "HTTP context");
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ if (isCachable(authScheme)) {
+ AuthCache authCache = clientContext.getAuthCache();
+ if (authCache == null) {
+ authCache = new BasicAuthCache();
+ clientContext.setAuthCache(authCache);
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Caching '" + authScheme.getSchemeName() +
+ "' auth scheme for " + authhost);
+ }
+ authCache.put(authhost, authScheme);
+ }
+ }
+
+ protected boolean isCachable(final AuthScheme authScheme) {
+ if (authScheme == null || !authScheme.isComplete()) {
+ return false;
+ }
+ final String schemeName = authScheme.getSchemeName();
+ return schemeName.equalsIgnoreCase(AuthSchemes.BASIC) ||
+ schemeName.equalsIgnoreCase(AuthSchemes.DIGEST);
+ }
+
+ public void authFailed(
+ final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
+ Args.notNull(authhost, "Host");
+ Args.notNull(context, "HTTP context");
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ final AuthCache authCache = clientContext.getAuthCache();
+ if (authCache != null) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Clearing cached auth scheme for " + authhost);
+ }
+ authCache.remove(authhost);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AutoRetryHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AutoRetryHttpClient.java
new file mode 100644
index 000000000..70c0e3404
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/AutoRetryHttpClient.java
@@ -0,0 +1,190 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.HttpClient;
+import ch.boye.httpclientandroidlib.client.ResponseHandler;
+import ch.boye.httpclientandroidlib.client.ServiceUnavailableRetryStrategy;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * {@link HttpClient} implementation that can automatically retry the request in case of
+ * a non-2xx response using the {@link ServiceUnavailableRetryStrategy} interface.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link HttpClientBuilder}.
+ */
+@Deprecated
+@ThreadSafe
+public class AutoRetryHttpClient implements HttpClient {
+
+ private final HttpClient backend;
+
+ private final ServiceUnavailableRetryStrategy retryStrategy;
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public AutoRetryHttpClient(
+ final HttpClient client, final ServiceUnavailableRetryStrategy retryStrategy) {
+ super();
+ Args.notNull(client, "HttpClient");
+ Args.notNull(retryStrategy, "ServiceUnavailableRetryStrategy");
+ this.backend = client;
+ this.retryStrategy = retryStrategy;
+ }
+
+ /**
+ * Constructs a {@code AutoRetryHttpClient} with default caching settings that
+ * stores cache entries in memory and uses a vanilla
+ * {@link DefaultHttpClient} for backend requests.
+ */
+ public AutoRetryHttpClient() {
+ this(new DefaultHttpClient(), new DefaultServiceUnavailableRetryStrategy());
+ }
+
+ /**
+ * Constructs a {@code AutoRetryHttpClient} with the given caching options that
+ * stores cache entries in memory and uses a vanilla
+ * {@link DefaultHttpClient} for backend requests.
+ *
+ * @param config
+ * retry configuration module options
+ */
+ public AutoRetryHttpClient(final ServiceUnavailableRetryStrategy config) {
+ this(new DefaultHttpClient(), config);
+ }
+
+ /**
+ * Constructs a {@code AutoRetryHttpClient} with default caching settings that
+ * stores cache entries in memory and uses the given {@link HttpClient} for
+ * backend requests.
+ *
+ * @param client
+ * used to make origin requests
+ */
+ public AutoRetryHttpClient(final HttpClient client) {
+ this(client, new DefaultServiceUnavailableRetryStrategy());
+ }
+
+ public HttpResponse execute(final HttpHost target, final HttpRequest request)
+ throws IOException {
+ final HttpContext defaultContext = null;
+ return execute(target, request, defaultContext);
+ }
+
+ public <T> T execute(final HttpHost target, final HttpRequest request,
+ final ResponseHandler<? extends T> responseHandler) throws IOException {
+ return execute(target, request, responseHandler, null);
+ }
+
+ public <T> T execute(final HttpHost target, final HttpRequest request,
+ final ResponseHandler<? extends T> responseHandler, final HttpContext context)
+ throws IOException {
+ final HttpResponse resp = execute(target, request, context);
+ return responseHandler.handleResponse(resp);
+ }
+
+ public HttpResponse execute(final HttpUriRequest request) throws IOException {
+ final HttpContext context = null;
+ return execute(request, context);
+ }
+
+ public HttpResponse execute(final HttpUriRequest request, final HttpContext context)
+ throws IOException {
+ final URI uri = request.getURI();
+ final HttpHost httpHost = new HttpHost(uri.getHost(), uri.getPort(),
+ uri.getScheme());
+ return execute(httpHost, request, context);
+ }
+
+ public <T> T execute(final HttpUriRequest request,
+ final ResponseHandler<? extends T> responseHandler) throws IOException {
+ return execute(request, responseHandler, null);
+ }
+
+ public <T> T execute(final HttpUriRequest request,
+ final ResponseHandler<? extends T> responseHandler, final HttpContext context)
+ throws IOException {
+ final HttpResponse resp = execute(request, context);
+ return responseHandler.handleResponse(resp);
+ }
+
+ public HttpResponse execute(final HttpHost target, final HttpRequest request,
+ final HttpContext context) throws IOException {
+ for (int c = 1;; c++) {
+ final HttpResponse response = backend.execute(target, request, context);
+ try {
+ if (retryStrategy.retryRequest(response, c, context)) {
+ EntityUtils.consume(response.getEntity());
+ final long nextInterval = retryStrategy.getRetryInterval();
+ try {
+ log.trace("Wait for " + nextInterval);
+ Thread.sleep(nextInterval);
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new InterruptedIOException();
+ }
+ } else {
+ return response;
+ }
+ } catch (final RuntimeException ex) {
+ try {
+ EntityUtils.consume(response.getEntity());
+ } catch (final IOException ioex) {
+ log.warn("I/O error consuming response content", ioex);
+ }
+ throw ex;
+ }
+ }
+ }
+
+ public ClientConnectionManager getConnectionManager() {
+ return backend.getConnectionManager();
+ }
+
+ public HttpParams getParams() {
+ return backend.getParams();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicAuthCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicAuthCache.java
new file mode 100644
index 000000000..810f73a0a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicAuthCache.java
@@ -0,0 +1,105 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.HashMap;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.client.AuthCache;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.conn.UnsupportedSchemeException;
+import ch.boye.httpclientandroidlib.impl.conn.DefaultSchemePortResolver;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of {@link AuthCache}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicAuthCache implements AuthCache {
+
+ private final HashMap<HttpHost, AuthScheme> map;
+ private final SchemePortResolver schemePortResolver;
+
+ /**
+ * Default constructor.
+ *
+ * @since 4.3
+ */
+ public BasicAuthCache(final SchemePortResolver schemePortResolver) {
+ super();
+ this.map = new HashMap<HttpHost, AuthScheme>();
+ this.schemePortResolver = schemePortResolver != null ? schemePortResolver :
+ DefaultSchemePortResolver.INSTANCE;
+ }
+
+ public BasicAuthCache() {
+ this(null);
+ }
+
+ protected HttpHost getKey(final HttpHost host) {
+ if (host.getPort() <= 0) {
+ final int port;
+ try {
+ port = schemePortResolver.resolve(host);
+ } catch (final UnsupportedSchemeException ignore) {
+ return host;
+ }
+ return new HttpHost(host.getHostName(), port, host.getSchemeName());
+ } else {
+ return host;
+ }
+ }
+
+ public void put(final HttpHost host, final AuthScheme authScheme) {
+ Args.notNull(host, "HTTP host");
+ this.map.put(getKey(host), authScheme);
+ }
+
+ public AuthScheme get(final HttpHost host) {
+ Args.notNull(host, "HTTP host");
+ return this.map.get(getKey(host));
+ }
+
+ public void remove(final HttpHost host) {
+ Args.notNull(host, "HTTP host");
+ this.map.remove(getKey(host));
+ }
+
+ public void clear() {
+ this.map.clear();
+ }
+
+ @Override
+ public String toString() {
+ return this.map.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCookieStore.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCookieStore.java
new file mode 100644
index 000000000..624a8f81d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCookieStore.java
@@ -0,0 +1,144 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieIdentityComparator;
+
+/**
+ * Default implementation of {@link CookieStore}
+ *
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class BasicCookieStore implements CookieStore, Serializable {
+
+ private static final long serialVersionUID = -7581093305228232025L;
+
+ @GuardedBy("this")
+ private final TreeSet<Cookie> cookies;
+
+ public BasicCookieStore() {
+ super();
+ this.cookies = new TreeSet<Cookie>(new CookieIdentityComparator());
+ }
+
+ /**
+ * Adds an {@link Cookie HTTP cookie}, replacing any existing equivalent cookies.
+ * If the given cookie has already expired it will not be added, but existing
+ * values will still be removed.
+ *
+ * @param cookie the {@link Cookie cookie} to be added
+ *
+ * @see #addCookies(Cookie[])
+ *
+ */
+ public synchronized void addCookie(final Cookie cookie) {
+ if (cookie != null) {
+ // first remove any old cookie that is equivalent
+ cookies.remove(cookie);
+ if (!cookie.isExpired(new Date())) {
+ cookies.add(cookie);
+ }
+ }
+ }
+
+ /**
+ * Adds an array of {@link Cookie HTTP cookies}. Cookies are added individually and
+ * in the given array order. If any of the given cookies has already expired it will
+ * not be added, but existing values will still be removed.
+ *
+ * @param cookies the {@link Cookie cookies} to be added
+ *
+ * @see #addCookie(Cookie)
+ *
+ */
+ public synchronized void addCookies(final Cookie[] cookies) {
+ if (cookies != null) {
+ for (final Cookie cooky : cookies) {
+ this.addCookie(cooky);
+ }
+ }
+ }
+
+ /**
+ * Returns an immutable array of {@link Cookie cookies} that this HTTP
+ * state currently contains.
+ *
+ * @return an array of {@link Cookie cookies}.
+ */
+ public synchronized List<Cookie> getCookies() {
+ //create defensive copy so it won't be concurrently modified
+ return new ArrayList<Cookie>(cookies);
+ }
+
+ /**
+ * Removes all of {@link Cookie cookies} in this HTTP state
+ * that have expired by the specified {@link java.util.Date date}.
+ *
+ * @return true if any cookies were purged.
+ *
+ * @see Cookie#isExpired(Date)
+ */
+ public synchronized boolean clearExpired(final Date date) {
+ if (date == null) {
+ return false;
+ }
+ boolean removed = false;
+ for (final Iterator<Cookie> it = cookies.iterator(); it.hasNext();) {
+ if (it.next().isExpired(date)) {
+ it.remove();
+ removed = true;
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * Clears all cookies.
+ */
+ public synchronized void clear() {
+ cookies.clear();
+ }
+
+ @Override
+ public synchronized String toString() {
+ return cookies.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCredentialsProvider.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCredentialsProvider.java
new file mode 100644
index 000000000..99c5cccc2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicCredentialsProvider.java
@@ -0,0 +1,109 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of {@link CredentialsProvider}.
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class BasicCredentialsProvider implements CredentialsProvider {
+
+ private final ConcurrentHashMap<AuthScope, Credentials> credMap;
+
+ /**
+ * Default constructor.
+ */
+ public BasicCredentialsProvider() {
+ super();
+ this.credMap = new ConcurrentHashMap<AuthScope, Credentials>();
+ }
+
+ public void setCredentials(
+ final AuthScope authscope,
+ final Credentials credentials) {
+ Args.notNull(authscope, "Authentication scope");
+ credMap.put(authscope, credentials);
+ }
+
+ /**
+ * Find matching {@link Credentials credentials} for the given authentication scope.
+ *
+ * @param map the credentials hash map
+ * @param authscope the {@link AuthScope authentication scope}
+ * @return the credentials
+ *
+ */
+ private static Credentials matchCredentials(
+ final Map<AuthScope, Credentials> map,
+ final AuthScope authscope) {
+ // see if we get a direct hit
+ Credentials creds = map.get(authscope);
+ if (creds == null) {
+ // Nope.
+ // Do a full scan
+ int bestMatchFactor = -1;
+ AuthScope bestMatch = null;
+ for (final AuthScope current: map.keySet()) {
+ final int factor = authscope.match(current);
+ if (factor > bestMatchFactor) {
+ bestMatchFactor = factor;
+ bestMatch = current;
+ }
+ }
+ if (bestMatch != null) {
+ creds = map.get(bestMatch);
+ }
+ }
+ return creds;
+ }
+
+ public Credentials getCredentials(final AuthScope authscope) {
+ Args.notNull(authscope, "Authentication scope");
+ return matchCredentials(this.credMap, authscope);
+ }
+
+ public void clear() {
+ this.credMap.clear();
+ }
+
+ @Override
+ public String toString() {
+ return credMap.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicResponseHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicResponseHandler.java
new file mode 100644
index 000000000..13ae4f856
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/BasicResponseHandler.java
@@ -0,0 +1,73 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.HttpResponseException;
+import ch.boye.httpclientandroidlib.client.ResponseHandler;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * A {@link ResponseHandler} that returns the response body as a String
+ * for successful (2xx) responses. If the response code was >= 300, the response
+ * body is consumed and an {@link HttpResponseException} is thrown.
+ * <p/>
+ * If this is used with
+ * {@link ch.boye.httpclientandroidlib.client.HttpClient#execute(
+ * ch.boye.httpclientandroidlib.client.methods.HttpUriRequest, ResponseHandler)},
+ * HttpClient may handle redirects (3xx responses) internally.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicResponseHandler implements ResponseHandler<String> {
+
+ /**
+ * Returns the response body as a String if the response was successful (a
+ * 2xx status code). If no response body exists, this returns null. If the
+ * response was unsuccessful (>= 300 status code), throws an
+ * {@link HttpResponseException}.
+ */
+ public String handleResponse(final HttpResponse response)
+ throws HttpResponseException, IOException {
+ final StatusLine statusLine = response.getStatusLine();
+ final HttpEntity entity = response.getEntity();
+ if (statusLine.getStatusCode() >= 300) {
+ EntityUtils.consume(entity);
+ throw new HttpResponseException(statusLine.getStatusCode(),
+ statusLine.getReasonPhrase());
+ }
+ return entity == null ? null : EntityUtils.toString(entity);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ClientParamsStack.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ClientParamsStack.java
new file mode 100644
index 000000000..37f5daedd
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ClientParamsStack.java
@@ -0,0 +1,269 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.AbstractHttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Represents a stack of parameter collections.
+ * When retrieving a parameter, the stack is searched in a fixed order
+ * and the first match returned. Setting parameters via the stack is
+ * not supported. To minimize overhead, the stack has a fixed size and
+ * does not maintain an internal array.
+ * The supported stack entries, sorted by increasing priority, are:
+ * <ol>
+ * <li>Application parameters:
+ * expected to be the same for all clients used by an application.
+ * These provide "global", that is application-wide, defaults.
+ * </li>
+ * <li>Client parameters:
+ * specific to an instance of
+ * {@link ch.boye.httpclientandroidlib.client.HttpClient HttpClient}.
+ * These provide client specific defaults.
+ * </li>
+ * <li>Request parameters:
+ * specific to a single request execution.
+ * For overriding client and global defaults.
+ * </li>
+ * <li>Override parameters:
+ * specific to an instance of
+ * {@link ch.boye.httpclientandroidlib.client.HttpClient HttpClient}.
+ * These can be used to set parameters that cannot be overridden
+ * on a per-request basis.
+ * </li>
+ * </ol>
+ * Each stack entry may be <code>null</code>. That is preferable over
+ * an empty params collection, since it avoids searching the empty collection
+ * when looking up parameters.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@NotThreadSafe
+@Deprecated
+public class ClientParamsStack extends AbstractHttpParams {
+
+ /** The application parameter collection, or <code>null</code>. */
+ protected final HttpParams applicationParams;
+
+ /** The client parameter collection, or <code>null</code>. */
+ protected final HttpParams clientParams;
+
+ /** The request parameter collection, or <code>null</code>. */
+ protected final HttpParams requestParams;
+
+ /** The override parameter collection, or <code>null</code>. */
+ protected final HttpParams overrideParams;
+
+
+ /**
+ * Creates a new parameter stack from elements.
+ * The arguments will be stored as-is, there is no copying to
+ * prevent modification.
+ *
+ * @param aparams application parameters, or <code>null</code>
+ * @param cparams client parameters, or <code>null</code>
+ * @param rparams request parameters, or <code>null</code>
+ * @param oparams override parameters, or <code>null</code>
+ */
+ public ClientParamsStack(final HttpParams aparams, final HttpParams cparams,
+ final HttpParams rparams, final HttpParams oparams) {
+ applicationParams = aparams;
+ clientParams = cparams;
+ requestParams = rparams;
+ overrideParams = oparams;
+ }
+
+
+ /**
+ * Creates a copy of a parameter stack.
+ * The new stack will have the exact same entries as the argument stack.
+ * There is no copying of parameters.
+ *
+ * @param stack the stack to copy
+ */
+ public ClientParamsStack(final ClientParamsStack stack) {
+ this(stack.getApplicationParams(),
+ stack.getClientParams(),
+ stack.getRequestParams(),
+ stack.getOverrideParams());
+ }
+
+
+ /**
+ * Creates a modified copy of a parameter stack.
+ * The new stack will contain the explicitly passed elements.
+ * For elements where the explicit argument is <code>null</code>,
+ * the corresponding element from the argument stack is used.
+ * There is no copying of parameters.
+ *
+ * @param stack the stack to modify
+ * @param aparams application parameters, or <code>null</code>
+ * @param cparams client parameters, or <code>null</code>
+ * @param rparams request parameters, or <code>null</code>
+ * @param oparams override parameters, or <code>null</code>
+ */
+ public ClientParamsStack(final ClientParamsStack stack,
+ final HttpParams aparams, final HttpParams cparams,
+ final HttpParams rparams, final HttpParams oparams) {
+ this((aparams != null) ? aparams : stack.getApplicationParams(),
+ (cparams != null) ? cparams : stack.getClientParams(),
+ (rparams != null) ? rparams : stack.getRequestParams(),
+ (oparams != null) ? oparams : stack.getOverrideParams());
+ }
+
+
+ /**
+ * Obtains the application parameters of this stack.
+ *
+ * @return the application parameters, or <code>null</code>
+ */
+ public final HttpParams getApplicationParams() {
+ return applicationParams;
+ }
+
+ /**
+ * Obtains the client parameters of this stack.
+ *
+ * @return the client parameters, or <code>null</code>
+ */
+ public final HttpParams getClientParams() {
+ return clientParams;
+ }
+
+ /**
+ * Obtains the request parameters of this stack.
+ *
+ * @return the request parameters, or <code>null</code>
+ */
+ public final HttpParams getRequestParams() {
+ return requestParams;
+ }
+
+ /**
+ * Obtains the override parameters of this stack.
+ *
+ * @return the override parameters, or <code>null</code>
+ */
+ public final HttpParams getOverrideParams() {
+ return overrideParams;
+ }
+
+
+ /**
+ * Obtains a parameter from this stack.
+ * See class comment for search order.
+ *
+ * @param name the name of the parameter to obtain
+ *
+ * @return the highest-priority value for that parameter, or
+ * <code>null</code> if it is not set anywhere in this stack
+ */
+ public Object getParameter(final String name) {
+ Args.notNull(name, "Parameter name");
+
+ Object result = null;
+
+ if (overrideParams != null) {
+ result = overrideParams.getParameter(name);
+ }
+ if ((result == null) && (requestParams != null)) {
+ result = requestParams.getParameter(name);
+ }
+ if ((result == null) && (clientParams != null)) {
+ result = clientParams.getParameter(name);
+ }
+ if ((result == null) && (applicationParams != null)) {
+ result = applicationParams.getParameter(name);
+ }
+ return result;
+ }
+
+ /**
+ * Does <i>not</i> set a parameter.
+ * Parameter stacks are read-only. It is possible, though discouraged,
+ * to access and modify specific stack entries.
+ * Derived classes may change this behavior.
+ *
+ * @param name ignored
+ * @param value ignored
+ *
+ * @return nothing
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public HttpParams setParameter(final String name, final Object value)
+ throws UnsupportedOperationException {
+
+ throw new UnsupportedOperationException
+ ("Setting parameters in a stack is not supported.");
+ }
+
+
+ /**
+ * Does <i>not</i> remove a parameter.
+ * Parameter stacks are read-only. It is possible, though discouraged,
+ * to access and modify specific stack entries.
+ * Derived classes may change this behavior.
+ *
+ * @param name ignored
+ *
+ * @return nothing
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public boolean removeParameter(final String name) {
+ throw new UnsupportedOperationException
+ ("Removing parameters in a stack is not supported.");
+ }
+
+
+ /**
+ * Does <i>not</i> copy parameters.
+ * Parameter stacks are lightweight objects, expected to be instantiated
+ * as needed and to be used only in a very specific context. On top of
+ * that, they are read-only. The typical copy operation to prevent
+ * accidental modification of parameters passed by the application to
+ * a framework object is therefore pointless and disabled.
+ * Create a new stack if you really need a copy.
+ * <br/>
+ * Derived classes may change this behavior.
+ *
+ * @return <code>this</code> parameter stack
+ */
+ public HttpParams copy() {
+ return this;
+ }
+
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/Clock.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/Clock.java
new file mode 100644
index 000000000..14eeec4a0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/Clock.java
@@ -0,0 +1,43 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+/**
+ * Interface used to enable easier testing of time-related behavior.
+ *
+ * @since 4.2
+ *
+ */
+interface Clock {
+
+ /**
+ * Returns the current time, expressed as the number of
+ * milliseconds since the epoch.
+ * @return current time
+ */
+ long getCurrentTime();
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpClient.java
new file mode 100644
index 000000000..c2fc5a5de
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpClient.java
@@ -0,0 +1,244 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.HttpClient;
+import ch.boye.httpclientandroidlib.client.ResponseHandler;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * Base implementation of {@link HttpClient} that also implements {@link Closeable}.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public abstract class CloseableHttpClient implements HttpClient, Closeable {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ protected abstract CloseableHttpResponse doExecute(HttpHost target, HttpRequest request,
+ HttpContext context) throws IOException, ClientProtocolException;
+
+ /**
+ * {@inheritDoc}
+ */
+ public CloseableHttpResponse execute(
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) throws IOException, ClientProtocolException {
+ return doExecute(target, request, context);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CloseableHttpResponse execute(
+ final HttpUriRequest request,
+ final HttpContext context) throws IOException, ClientProtocolException {
+ Args.notNull(request, "HTTP request");
+ return doExecute(determineTarget(request), request, context);
+ }
+
+ private static HttpHost determineTarget(final HttpUriRequest request) throws ClientProtocolException {
+ // A null target may be acceptable if there is a default target.
+ // Otherwise, the null target is detected in the director.
+ HttpHost target = null;
+
+ final URI requestURI = request.getURI();
+ if (requestURI.isAbsolute()) {
+ target = URIUtils.extractHost(requestURI);
+ if (target == null) {
+ throw new ClientProtocolException("URI does not specify a valid host name: "
+ + requestURI);
+ }
+ }
+ return target;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CloseableHttpResponse execute(
+ final HttpUriRequest request) throws IOException, ClientProtocolException {
+ return execute(request, (HttpContext) null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CloseableHttpResponse execute(
+ final HttpHost target,
+ final HttpRequest request) throws IOException, ClientProtocolException {
+ return doExecute(target, request, (HttpContext) null);
+ }
+
+ /**
+ * Executes a request using the default context and processes the
+ * response using the given response handler. The content entity associated
+ * with the response is fully consumed and the underlying connection is
+ * released back to the connection manager automatically in all cases
+ * relieving individual {@link ResponseHandler}s from having to manage
+ * resource deallocation internally.
+ *
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ public <T> T execute(final HttpUriRequest request,
+ final ResponseHandler<? extends T> responseHandler) throws IOException,
+ ClientProtocolException {
+ return execute(request, responseHandler, null);
+ }
+
+ /**
+ * Executes a request using the default context and processes the
+ * response using the given response handler. The content entity associated
+ * with the response is fully consumed and the underlying connection is
+ * released back to the connection manager automatically in all cases
+ * relieving individual {@link ResponseHandler}s from having to manage
+ * resource deallocation internally.
+ *
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ * @param context the context to use for the execution, or
+ * <code>null</code> to use the default context
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ public <T> T execute(final HttpUriRequest request,
+ final ResponseHandler<? extends T> responseHandler, final HttpContext context)
+ throws IOException, ClientProtocolException {
+ final HttpHost target = determineTarget(request);
+ return execute(target, request, responseHandler, context);
+ }
+
+ /**
+ * Executes a request using the default context and processes the
+ * response using the given response handler. The content entity associated
+ * with the response is fully consumed and the underlying connection is
+ * released back to the connection manager automatically in all cases
+ * relieving individual {@link ResponseHandler}s from having to manage
+ * resource deallocation internally.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ public <T> T execute(final HttpHost target, final HttpRequest request,
+ final ResponseHandler<? extends T> responseHandler) throws IOException,
+ ClientProtocolException {
+ return execute(target, request, responseHandler, null);
+ }
+
+ /**
+ * Executes a request using the default context and processes the
+ * response using the given response handler. The content entity associated
+ * with the response is fully consumed and the underlying connection is
+ * released back to the connection manager automatically in all cases
+ * relieving individual {@link ResponseHandler}s from having to manage
+ * resource deallocation internally.
+ *
+ * @param target the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param responseHandler the response handler
+ * @param context the context to use for the execution, or
+ * <code>null</code> to use the default context
+ *
+ * @return the response object as generated by the response handler.
+ * @throws IOException in case of a problem or the connection was aborted
+ * @throws ClientProtocolException in case of an http protocol error
+ */
+ public <T> T execute(final HttpHost target, final HttpRequest request,
+ final ResponseHandler<? extends T> responseHandler, final HttpContext context)
+ throws IOException, ClientProtocolException {
+ Args.notNull(responseHandler, "Response handler");
+
+ final HttpResponse response = execute(target, request, context);
+
+ final T result;
+ try {
+ result = responseHandler.handleResponse(response);
+ } catch (final Exception t) {
+ final HttpEntity entity = response.getEntity();
+ try {
+ EntityUtils.consume(entity);
+ } catch (final Exception t2) {
+ // Log this exception. The original exception is more
+ // important and will be thrown to the caller.
+ this.log.warn("Error consuming content after an exception.", t2);
+ }
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
+ }
+ if (t instanceof IOException) {
+ throw (IOException) t;
+ }
+ throw new UndeclaredThrowableException(t);
+ }
+
+ // Handling the response was successful. Ensure that the content has
+ // been fully consumed.
+ final HttpEntity entity = response.getEntity();
+ EntityUtils.consume(entity);
+ return result;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpResponseProxy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpResponseProxy.java
new file mode 100644
index 000000000..9869740df
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/CloseableHttpResponseProxy.java
@@ -0,0 +1,87 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * @since 4.3
+ */
+@NotThreadSafe
+class CloseableHttpResponseProxy implements InvocationHandler {
+
+ private final HttpResponse original;
+
+ CloseableHttpResponseProxy(final HttpResponse original) {
+ super();
+ this.original = original;
+ }
+
+ public void close() throws IOException {
+ final HttpEntity entity = this.original.getEntity();
+ EntityUtils.consume(entity);
+ }
+
+ public Object invoke(
+ final Object proxy, final Method method, final Object[] args) throws Throwable {
+ final String mname = method.getName();
+ if (mname.equals("close")) {
+ close();
+ return null;
+ } else {
+ try {
+ return method.invoke(original, args);
+ } catch (final InvocationTargetException ex) {
+ final Throwable cause = ex.getCause();
+ if (cause != null) {
+ throw cause;
+ } else {
+ throw ex;
+ }
+ }
+ }
+ }
+
+ public static CloseableHttpResponse newProxy(final HttpResponse original) {
+ return (CloseableHttpResponse) Proxy.newProxyInstance(
+ CloseableHttpResponseProxy.class.getClassLoader(),
+ new Class<?>[] { CloseableHttpResponse.class },
+ new CloseableHttpResponseProxy(original));
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ContentEncodingHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ContentEncodingHttpClient.java
new file mode 100644
index 000000000..f4169225e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ContentEncodingHttpClient.java
@@ -0,0 +1,93 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.protocol.RequestAcceptEncoding;
+import ch.boye.httpclientandroidlib.client.protocol.ResponseContentEncoding;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpProcessor;
+
+/**
+ * {@link DefaultHttpClient} sub-class which includes a {@link RequestAcceptEncoding}
+ * for the request and response.
+ *
+ * <b>Deprecation note:</b> due to the way this class modifies a response body
+ * without changing the response headers to reflect the entity changes, it cannot
+ * be used as the &quot;backend&quot; for a caching {@link
+ * ch.boye.httpclientandroidlib.client.HttpClient} and still have uncompressed responses be cached.
+ * Users are encouraged to use the {@link DecompressingHttpClient} instead
+ * of this class, which can be wired in either before or after caching, depending on
+ * whether you want to cache responses in compressed or uncompressed form.
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.2) use {@link HttpClientBuilder}
+ */
+@Deprecated
+@ThreadSafe // since DefaultHttpClient is
+public class ContentEncodingHttpClient extends DefaultHttpClient {
+
+ /**
+ * Creates a new HTTP client from parameters and a connection manager.
+ *
+ * @param params the parameters
+ * @param conman the connection manager
+ */
+ public ContentEncodingHttpClient(final ClientConnectionManager conman, final HttpParams params) {
+ super(conman, params);
+ }
+
+ /**
+ * @param params
+ */
+ public ContentEncodingHttpClient(final HttpParams params) {
+ this(null, params);
+ }
+
+ /**
+ *
+ */
+ public ContentEncodingHttpClient() {
+ this(null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected BasicHttpProcessor createHttpProcessor() {
+ final BasicHttpProcessor result = super.createHttpProcessor();
+
+ result.addRequestInterceptor(new RequestAcceptEncoding());
+ result.addResponseInterceptor(new ResponseContentEncoding());
+
+ return result;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DecompressingHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DecompressingHttpClient.java
new file mode 100644
index 000000000..4d55303ad
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DecompressingHttpClient.java
@@ -0,0 +1,214 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.HttpClient;
+import ch.boye.httpclientandroidlib.client.ResponseHandler;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.client.protocol.RequestAcceptEncoding;
+import ch.boye.httpclientandroidlib.client.protocol.ResponseContentEncoding;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * <p>Decorator adding support for compressed responses. This class sets
+ * the <code>Accept-Encoding</code> header on requests to indicate
+ * support for the <code>gzip</code> and <code>deflate</code>
+ * compression schemes; it then checks the <code>Content-Encoding</code>
+ * header on the response to uncompress any compressed response bodies.
+ * The {@link java.io.InputStream} of the entity will contain the uncompressed
+ * content.</p>
+ *
+ * <p><b>N.B.</b> Any upstream clients of this class need to be aware that
+ * this effectively obscures visibility into the length of a server
+ * response body, since the <code>Content-Length</code> header will
+ * correspond to the compressed entity length received from the server,
+ * but the content length experienced by reading the response body may
+ * be different (hopefully higher!).</p>
+ *
+ * <p>That said, this decorator is compatible with the
+ * <code>CachingHttpClient</code> in that the two decorators can be added
+ * in either order and still have cacheable responses be cached.</p>
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link HttpClientBuilder}
+ */
+@Deprecated
+public class DecompressingHttpClient implements HttpClient {
+
+ private final HttpClient backend;
+ private final HttpRequestInterceptor acceptEncodingInterceptor;
+ private final HttpResponseInterceptor contentEncodingInterceptor;
+
+ /**
+ * Constructs a decorator to ask for and handle compressed
+ * entities on the fly.
+ */
+ public DecompressingHttpClient() {
+ this(new DefaultHttpClient());
+ }
+
+ /**
+ * Constructs a decorator to ask for and handle compressed
+ * entities on the fly.
+ * @param backend the {@link HttpClient} to use for actually
+ * issuing requests
+ */
+ public DecompressingHttpClient(final HttpClient backend) {
+ this(backend, new RequestAcceptEncoding(), new ResponseContentEncoding());
+ }
+
+ DecompressingHttpClient(final HttpClient backend,
+ final HttpRequestInterceptor requestInterceptor,
+ final HttpResponseInterceptor responseInterceptor) {
+ this.backend = backend;
+ this.acceptEncodingInterceptor = requestInterceptor;
+ this.contentEncodingInterceptor = responseInterceptor;
+ }
+
+ public HttpParams getParams() {
+ return backend.getParams();
+ }
+
+ public ClientConnectionManager getConnectionManager() {
+ return backend.getConnectionManager();
+ }
+
+ public HttpResponse execute(final HttpUriRequest request) throws IOException,
+ ClientProtocolException {
+ return execute(getHttpHost(request), request, (HttpContext)null);
+ }
+
+ /**
+ * Gets the HttpClient to issue request.
+ *
+ * @return the HttpClient to issue request
+ */
+ public HttpClient getHttpClient() {
+ return this.backend;
+ }
+
+ HttpHost getHttpHost(final HttpUriRequest request) {
+ final URI uri = request.getURI();
+ return URIUtils.extractHost(uri);
+ }
+
+ public HttpResponse execute(final HttpUriRequest request, final HttpContext context)
+ throws IOException, ClientProtocolException {
+ return execute(getHttpHost(request), request, context);
+ }
+
+ public HttpResponse execute(final HttpHost target, final HttpRequest request)
+ throws IOException, ClientProtocolException {
+ return execute(target, request, (HttpContext)null);
+ }
+
+ public HttpResponse execute(final HttpHost target, final HttpRequest request,
+ final HttpContext context) throws IOException, ClientProtocolException {
+ try {
+ final HttpContext localContext = context != null ? context : new BasicHttpContext();
+ final HttpRequest wrapped;
+ if (request instanceof HttpEntityEnclosingRequest) {
+ wrapped = new EntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request);
+ } else {
+ wrapped = new RequestWrapper(request);
+ }
+ acceptEncodingInterceptor.process(wrapped, localContext);
+ final HttpResponse response = backend.execute(target, wrapped, localContext);
+ try {
+ contentEncodingInterceptor.process(response, localContext);
+ if (Boolean.TRUE.equals(localContext.getAttribute(ResponseContentEncoding.UNCOMPRESSED))) {
+ response.removeHeaders("Content-Length");
+ response.removeHeaders("Content-Encoding");
+ response.removeHeaders("Content-MD5");
+ }
+ return response;
+ } catch (final HttpException ex) {
+ EntityUtils.consume(response.getEntity());
+ throw ex;
+ } catch (final IOException ex) {
+ EntityUtils.consume(response.getEntity());
+ throw ex;
+ } catch (final RuntimeException ex) {
+ EntityUtils.consume(response.getEntity());
+ throw ex;
+ }
+ } catch (final HttpException e) {
+ throw new ClientProtocolException(e);
+ }
+ }
+
+ public <T> T execute(final HttpUriRequest request,
+ final ResponseHandler<? extends T> responseHandler) throws IOException,
+ ClientProtocolException {
+ return execute(getHttpHost(request), request, responseHandler);
+ }
+
+ public <T> T execute(final HttpUriRequest request,
+ final ResponseHandler<? extends T> responseHandler, final HttpContext context)
+ throws IOException, ClientProtocolException {
+ return execute(getHttpHost(request), request, responseHandler, context);
+ }
+
+ public <T> T execute(final HttpHost target, final HttpRequest request,
+ final ResponseHandler<? extends T> responseHandler) throws IOException,
+ ClientProtocolException {
+ return execute(target, request, responseHandler, null);
+ }
+
+ public <T> T execute(final HttpHost target, final HttpRequest request,
+ final ResponseHandler<? extends T> responseHandler, final HttpContext context)
+ throws IOException, ClientProtocolException {
+ final HttpResponse response = execute(target, request, context);
+ try {
+ return responseHandler.handleResponse(response);
+ } finally {
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ EntityUtils.consume(entity);
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultBackoffStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultBackoffStrategy.java
new file mode 100644
index 000000000..5a5e67caa
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultBackoffStrategy.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.client.ConnectionBackoffStrategy;
+
+/**
+ * This {@link ConnectionBackoffStrategy} backs off either for a raw
+ * network socket or connection timeout or if the server explicitly
+ * sends a 503 (Service Unavailable) response.
+ *
+ * @since 4.2
+ */
+public class DefaultBackoffStrategy implements ConnectionBackoffStrategy {
+
+ public boolean shouldBackoff(final Throwable t) {
+ return (t instanceof SocketTimeoutException
+ || t instanceof ConnectException);
+ }
+
+ public boolean shouldBackoff(final HttpResponse resp) {
+ return (resp.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java
new file mode 100644
index 000000000..a5524bd43
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HeaderElementIterator;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy;
+import ch.boye.httpclientandroidlib.message.BasicHeaderElementIterator;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of a strategy deciding duration
+ * that a connection can remain idle.
+ *
+ * The default implementation looks solely at the 'Keep-Alive'
+ * header's timeout token.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class DefaultConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {
+
+ public static final DefaultConnectionKeepAliveStrategy INSTANCE = new DefaultConnectionKeepAliveStrategy();
+
+ public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {
+ Args.notNull(response, "HTTP response");
+ final HeaderElementIterator it = new BasicHeaderElementIterator(
+ response.headerIterator(HTTP.CONN_KEEP_ALIVE));
+ while (it.hasNext()) {
+ final HeaderElement he = it.nextElement();
+ final String param = he.getName();
+ final String value = he.getValue();
+ if (value != null && param.equalsIgnoreCase("timeout")) {
+ try {
+ return Long.parseLong(value) * 1000;
+ } catch(final NumberFormatException ignore) {
+ }
+ }
+ }
+ return -1;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpClient.java
new file mode 100644
index 000000000..55e5ab07e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpClient.java
@@ -0,0 +1,225 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.protocol.RequestAddCookies;
+import ch.boye.httpclientandroidlib.client.protocol.RequestAuthCache;
+import ch.boye.httpclientandroidlib.client.protocol.RequestClientConnControl;
+import ch.boye.httpclientandroidlib.client.protocol.RequestDefaultHeaders;
+import ch.boye.httpclientandroidlib.client.protocol.RequestProxyAuthentication;
+import ch.boye.httpclientandroidlib.client.protocol.RequestTargetAuthentication;
+import ch.boye.httpclientandroidlib.client.protocol.ResponseProcessCookies;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.params.HttpProtocolParams;
+import ch.boye.httpclientandroidlib.params.SyncBasicHttpParams;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.RequestContent;
+import ch.boye.httpclientandroidlib.protocol.RequestExpectContinue;
+import ch.boye.httpclientandroidlib.protocol.RequestTargetHost;
+import ch.boye.httpclientandroidlib.protocol.RequestUserAgent;
+
+/**
+ * Default implementation of {@link ch.boye.httpclientandroidlib.client.HttpClient} pre-configured
+ * for most common use scenarios.
+ * <p>
+ * Please see the Javadoc for {@link #createHttpProcessor()} for the details of the interceptors
+ * that are set up by default.
+ * <p>
+ * Additional interceptors can be added as follows, but
+ * take care not to add the same interceptor more than once.
+ * <pre>
+ * DefaultHttpClient httpclient = new DefaultHttpClient();
+ * httpclient.addRequestInterceptor(new RequestAcceptEncoding());
+ * httpclient.addResponseInterceptor(new ResponseContentEncoding());
+ * </pre>
+ * <p>
+ * This class sets up the following parameters if not explicitly set:
+ * <ul>
+ * <li>Version: HttpVersion.HTTP_1_1</li>
+ * <li>ContentCharset: HTTP.DEFAULT_CONTENT_CHARSET</li>
+ * <li>NoTcpDelay: true</li>
+ * <li>SocketBufferSize: 8192</li>
+ * <li>UserAgent: Apache-HttpClient/release (java 1.5)</li>
+ * </ul>
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#PROTOCOL_VERSION}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#USE_EXPECT_CONTINUE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#WAIT_FOR_CONTINUE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#USER_AGENT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#TCP_NODELAY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_LINGER}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_REUSEADDR}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#STALE_CONNECTION_CHECK}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#FORCED_ROUTE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#LOCAL_ADDRESS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#DEFAULT_PROXY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#DATE_PATTERNS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#SINGLE_COOKIE_HEADER}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.auth.params.AuthPNames#CREDENTIAL_CHARSET}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#COOKIE_POLICY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#HANDLE_AUTHENTICATION}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#HANDLE_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#MAX_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#ALLOW_CIRCULAR_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#VIRTUAL_HOST}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#DEFAULT_HOST}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#DEFAULT_HEADERS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#CONN_MANAGER_TIMEOUT}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link HttpClientBuilder}.
+ */
+@ThreadSafe
+@Deprecated
+public class DefaultHttpClient extends AbstractHttpClient {
+
+ /**
+ * Creates a new HTTP client from parameters and a connection manager.
+ *
+ * @param params the parameters
+ * @param conman the connection manager
+ */
+ public DefaultHttpClient(
+ final ClientConnectionManager conman,
+ final HttpParams params) {
+ super(conman, params);
+ }
+
+
+ /**
+ * @since 4.1
+ */
+ public DefaultHttpClient(
+ final ClientConnectionManager conman) {
+ super(conman, null);
+ }
+
+
+ public DefaultHttpClient(final HttpParams params) {
+ super(null, params);
+ }
+
+
+ public DefaultHttpClient() {
+ super(null, null);
+ }
+
+
+ /**
+ * Creates the default set of HttpParams by invoking {@link DefaultHttpClient#setDefaultHttpParams(HttpParams)}
+ *
+ * @return a new instance of {@link SyncBasicHttpParams} with the defaults applied to it.
+ */
+ @Override
+ protected HttpParams createHttpParams() {
+ final HttpParams params = new SyncBasicHttpParams();
+ setDefaultHttpParams(params);
+ return params;
+ }
+
+ /**
+ * Saves the default set of HttpParams in the provided parameter.
+ * These are:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#PROTOCOL_VERSION}:
+ * 1.1</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#HTTP_CONTENT_CHARSET}:
+ * ISO-8859-1</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#TCP_NODELAY}:
+ * true</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}:
+ * 8192</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#USER_AGENT}:
+ * Apache-HttpClient/<release> (java 1.5)</li>
+ * </ul>
+ */
+ public static void setDefaultHttpParams(final HttpParams params) {
+ HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
+ HttpProtocolParams.setContentCharset(params, HTTP.DEF_CONTENT_CHARSET.name());
+ HttpConnectionParams.setTcpNoDelay(params, true);
+ HttpConnectionParams.setSocketBufferSize(params, 8192);
+ HttpProtocolParams.setUserAgent(params, HttpClientBuilder.DEFAULT_USER_AGENT);
+ }
+
+ /**
+ * Create the processor with the following interceptors:
+ * <ul>
+ * <li>{@link RequestDefaultHeaders}</li>
+ * <li>{@link RequestContent}</li>
+ * <li>{@link RequestTargetHost}</li>
+ * <li>{@link RequestClientConnControl}</li>
+ * <li>{@link RequestUserAgent}</li>
+ * <li>{@link RequestExpectContinue}</li>
+ * <li>{@link RequestAddCookies}</li>
+ * <li>{@link ResponseProcessCookies}</li>
+ * <li>{@link RequestAuthCache}</li>
+ * <li>{@link RequestTargetAuthentication}</li>
+ * <li>{@link RequestProxyAuthentication}</li>
+ * </ul>
+ * <p>
+ * @return the processor with the added interceptors.
+ */
+ @Override
+ protected BasicHttpProcessor createHttpProcessor() {
+ final BasicHttpProcessor httpproc = new BasicHttpProcessor();
+ httpproc.addInterceptor(new RequestDefaultHeaders());
+ // Required protocol interceptors
+ httpproc.addInterceptor(new RequestContent());
+ httpproc.addInterceptor(new RequestTargetHost());
+ // Recommended protocol interceptors
+ httpproc.addInterceptor(new RequestClientConnControl());
+ httpproc.addInterceptor(new RequestUserAgent());
+ httpproc.addInterceptor(new RequestExpectContinue());
+ // HTTP state management interceptors
+ httpproc.addInterceptor(new RequestAddCookies());
+ httpproc.addInterceptor(new ResponseProcessCookies());
+ // HTTP authentication interceptors
+ httpproc.addInterceptor(new RequestAuthCache());
+ httpproc.addInterceptor(new RequestTargetAuthentication());
+ httpproc.addInterceptor(new RequestProxyAuthentication());
+ return httpproc;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java
new file mode 100644
index 000000000..1721c8e70
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java
@@ -0,0 +1,203 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.ConnectException;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.net.ssl.SSLException;
+
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * The default {@link HttpRequestRetryHandler} used by request executors.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class DefaultHttpRequestRetryHandler implements HttpRequestRetryHandler {
+
+ public static final DefaultHttpRequestRetryHandler INSTANCE = new DefaultHttpRequestRetryHandler();
+
+ /** the number of times a method will be retried */
+ private final int retryCount;
+
+ /** Whether or not methods that have successfully sent their request will be retried */
+ private final boolean requestSentRetryEnabled;
+
+ private final Set<Class<? extends IOException>> nonRetriableClasses;
+
+ /**
+ * Create the request retry handler using the specified IOException classes
+ *
+ * @param retryCount how many times to retry; 0 means no retries
+ * @param requestSentRetryEnabled true if it's OK to retry requests that have been sent
+ * @param clazzes the IOException types that should not be retried
+ * @since 4.3
+ */
+ protected DefaultHttpRequestRetryHandler(
+ final int retryCount,
+ final boolean requestSentRetryEnabled,
+ final Collection<Class<? extends IOException>> clazzes) {
+ super();
+ this.retryCount = retryCount;
+ this.requestSentRetryEnabled = requestSentRetryEnabled;
+ this.nonRetriableClasses = new HashSet<Class<? extends IOException>>();
+ for (final Class<? extends IOException> clazz: clazzes) {
+ this.nonRetriableClasses.add(clazz);
+ }
+ }
+
+ /**
+ * Create the request retry handler using the following list of
+ * non-retriable IOException classes: <br>
+ * <ul>
+ * <li>InterruptedIOException</li>
+ * <li>UnknownHostException</li>
+ * <li>ConnectException</li>
+ * <li>SSLException</li>
+ * </ul>
+ * @param retryCount how many times to retry; 0 means no retries
+ * @param requestSentRetryEnabled true if it's OK to retry requests that have been sent
+ */
+ @SuppressWarnings("unchecked")
+ public DefaultHttpRequestRetryHandler(final int retryCount, final boolean requestSentRetryEnabled) {
+ this(retryCount, requestSentRetryEnabled, Arrays.asList(
+ InterruptedIOException.class,
+ UnknownHostException.class,
+ ConnectException.class,
+ SSLException.class));
+ }
+
+ /**
+ * Create the request retry handler with a retry count of 3, requestSentRetryEnabled false
+ * and using the following list of non-retriable IOException classes: <br>
+ * <ul>
+ * <li>InterruptedIOException</li>
+ * <li>UnknownHostException</li>
+ * <li>ConnectException</li>
+ * <li>SSLException</li>
+ * </ul>
+ */
+ public DefaultHttpRequestRetryHandler() {
+ this(3, false);
+ }
+ /**
+ * Used <code>retryCount</code> and <code>requestSentRetryEnabled</code> to determine
+ * if the given method should be retried.
+ */
+ public boolean retryRequest(
+ final IOException exception,
+ final int executionCount,
+ final HttpContext context) {
+ Args.notNull(exception, "Exception parameter");
+ Args.notNull(context, "HTTP context");
+ if (executionCount > this.retryCount) {
+ // Do not retry if over max retry count
+ return false;
+ }
+ if (this.nonRetriableClasses.contains(exception.getClass())) {
+ return false;
+ } else {
+ for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
+ if (rejectException.isInstance(exception)) {
+ return false;
+ }
+ }
+ }
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+ final HttpRequest request = clientContext.getRequest();
+
+ if(requestIsAborted(request)){
+ return false;
+ }
+
+ if (handleAsIdempotent(request)) {
+ // Retry if the request is considered idempotent
+ return true;
+ }
+
+ if (!clientContext.isRequestSent() || this.requestSentRetryEnabled) {
+ // Retry if the request has not been sent fully or
+ // if it's OK to retry methods that have been sent
+ return true;
+ }
+ // otherwise do not retry
+ return false;
+ }
+
+ /**
+ * @return <code>true</code> if this handler will retry methods that have
+ * successfully sent their request, <code>false</code> otherwise
+ */
+ public boolean isRequestSentRetryEnabled() {
+ return requestSentRetryEnabled;
+ }
+
+ /**
+ * @return the maximum number of times a method will be retried
+ */
+ public int getRetryCount() {
+ return retryCount;
+ }
+
+ /**
+ * @since 4.2
+ */
+ protected boolean handleAsIdempotent(final HttpRequest request) {
+ return !(request instanceof HttpEntityEnclosingRequest);
+ }
+
+ /**
+ * @since 4.2
+ *
+ * @deprecated (4.3)
+ */
+ @Deprecated
+ protected boolean requestIsAborted(final HttpRequest request) {
+ HttpRequest req = request;
+ if (request instanceof RequestWrapper) { // does not forward request to original
+ req = ((RequestWrapper) request).getOriginal();
+ }
+ return (req instanceof HttpUriRequest && ((HttpUriRequest)req).isAborted());
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java
new file mode 100644
index 000000000..a70057ae5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java
@@ -0,0 +1,90 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.List;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.auth.params.AuthPNames;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default {@link ch.boye.httpclientandroidlib.client.AuthenticationHandler} implementation
+ * for proxy host authentication.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ProxyAuthenticationStrategy}
+ */
+@Deprecated
+@Immutable
+public class DefaultProxyAuthenticationHandler extends AbstractAuthenticationHandler {
+
+ public DefaultProxyAuthenticationHandler() {
+ super();
+ }
+
+ public boolean isAuthenticationRequested(
+ final HttpResponse response,
+ final HttpContext context) {
+ Args.notNull(response, "HTTP response");
+ final int status = response.getStatusLine().getStatusCode();
+ return status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED;
+ }
+
+ public Map<String, Header> getChallenges(
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ Args.notNull(response, "HTTP response");
+ final Header[] headers = response.getHeaders(AUTH.PROXY_AUTH);
+ return parseChallenges(headers);
+ }
+
+ @Override
+ protected List<String> getAuthPreferences(
+ final HttpResponse response,
+ final HttpContext context) {
+ @SuppressWarnings("unchecked")
+ final
+ List<String> authpref = (List<String>) response.getParams().getParameter(
+ AuthPNames.PROXY_AUTH_PREF);
+ if (authpref != null) {
+ return authpref;
+ } else {
+ return super.getAuthPreferences(response, context);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectHandler.java
new file mode 100644
index 000000000..6bd58c035
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectHandler.java
@@ -0,0 +1,180 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.CircularRedirectException;
+import ch.boye.httpclientandroidlib.client.RedirectHandler;
+import ch.boye.httpclientandroidlib.client.methods.HttpGet;
+import ch.boye.httpclientandroidlib.client.methods.HttpHead;
+import ch.boye.httpclientandroidlib.client.params.ClientPNames;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Default implementation of {@link RedirectHandler}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) use {@link DefaultRedirectStrategy}.
+ */
+@Immutable
+@Deprecated
+public class DefaultRedirectHandler implements RedirectHandler {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations";
+
+ public DefaultRedirectHandler() {
+ super();
+ }
+
+ public boolean isRedirectRequested(
+ final HttpResponse response,
+ final HttpContext context) {
+ Args.notNull(response, "HTTP response");
+
+ final int statusCode = response.getStatusLine().getStatusCode();
+ switch (statusCode) {
+ case HttpStatus.SC_MOVED_TEMPORARILY:
+ case HttpStatus.SC_MOVED_PERMANENTLY:
+ case HttpStatus.SC_TEMPORARY_REDIRECT:
+ final HttpRequest request = (HttpRequest) context.getAttribute(
+ ExecutionContext.HTTP_REQUEST);
+ final String method = request.getRequestLine().getMethod();
+ return method.equalsIgnoreCase(HttpGet.METHOD_NAME)
+ || method.equalsIgnoreCase(HttpHead.METHOD_NAME);
+ case HttpStatus.SC_SEE_OTHER:
+ return true;
+ default:
+ return false;
+ } //end of switch
+ }
+
+ public URI getLocationURI(
+ final HttpResponse response,
+ final HttpContext context) throws ProtocolException {
+ Args.notNull(response, "HTTP response");
+ //get the location header to find out where to redirect to
+ final Header locationHeader = response.getFirstHeader("location");
+ if (locationHeader == null) {
+ // got a redirect response, but no location header
+ throw new ProtocolException(
+ "Received redirect response " + response.getStatusLine()
+ + " but no location header");
+ }
+ final String location = locationHeader.getValue();
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Redirect requested to location '" + location + "'");
+ }
+
+ URI uri;
+ try {
+ uri = new URI(location);
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException("Invalid redirect URI: " + location, ex);
+ }
+
+ final HttpParams params = response.getParams();
+ // rfc2616 demands the location value be a complete URI
+ // Location = "Location" ":" absoluteURI
+ if (!uri.isAbsolute()) {
+ if (params.isParameterTrue(ClientPNames.REJECT_RELATIVE_REDIRECT)) {
+ throw new ProtocolException("Relative redirect location '"
+ + uri + "' not allowed");
+ }
+ // Adjust location URI
+ final HttpHost target = (HttpHost) context.getAttribute(
+ ExecutionContext.HTTP_TARGET_HOST);
+ Asserts.notNull(target, "Target host");
+
+ final HttpRequest request = (HttpRequest) context.getAttribute(
+ ExecutionContext.HTTP_REQUEST);
+
+ try {
+ final URI requestURI = new URI(request.getRequestLine().getUri());
+ final URI absoluteRequestURI = URIUtils.rewriteURI(requestURI, target, true);
+ uri = URIUtils.resolve(absoluteRequestURI, uri);
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException(ex.getMessage(), ex);
+ }
+ }
+
+ if (params.isParameterFalse(ClientPNames.ALLOW_CIRCULAR_REDIRECTS)) {
+
+ RedirectLocations redirectLocations = (RedirectLocations) context.getAttribute(
+ REDIRECT_LOCATIONS);
+
+ if (redirectLocations == null) {
+ redirectLocations = new RedirectLocations();
+ context.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
+ }
+
+ final URI redirectURI;
+ if (uri.getFragment() != null) {
+ try {
+ final HttpHost target = new HttpHost(
+ uri.getHost(),
+ uri.getPort(),
+ uri.getScheme());
+ redirectURI = URIUtils.rewriteURI(uri, target, true);
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException(ex.getMessage(), ex);
+ }
+ } else {
+ redirectURI = uri;
+ }
+
+ if (redirectLocations.contains(redirectURI)) {
+ throw new CircularRedirectException("Circular redirect to '" +
+ redirectURI + "'");
+ } else {
+ redirectLocations.add(redirectURI);
+ }
+ }
+
+ return uri;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategy.java
new file mode 100644
index 000000000..e7d9315d2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategy.java
@@ -0,0 +1,233 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.CircularRedirectException;
+import ch.boye.httpclientandroidlib.client.RedirectStrategy;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.HttpGet;
+import ch.boye.httpclientandroidlib.client.methods.HttpHead;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.client.methods.RequestBuilder;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.client.utils.URIBuilder;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+/**
+ * Default implementation of {@link RedirectStrategy}. This strategy honors the restrictions
+ * on automatic redirection of entity enclosing methods such as POST and PUT imposed by the
+ * HTTP specification. <tt>302 Moved Temporarily</tt>, <tt>301 Moved Permanently</tt> and
+ * <tt>307 Temporary Redirect</tt> status codes will result in an automatic redirect of
+ * HEAD and GET methods only. POST and PUT methods will not be automatically redirected
+ * as requiring user confirmation.
+ * <p/>
+ * The restriction on automatic redirection of POST methods can be relaxed by using
+ * {@link LaxRedirectStrategy} instead of {@link DefaultRedirectStrategy}.
+ *
+ * @see LaxRedirectStrategy
+ * @since 4.1
+ */
+@Immutable
+public class DefaultRedirectStrategy implements RedirectStrategy {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /**
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.protocol.HttpClientContext#REDIRECT_LOCATIONS}.
+ */
+ @Deprecated
+ public static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations";
+
+ public static final DefaultRedirectStrategy INSTANCE = new DefaultRedirectStrategy();
+
+ /**
+ * Redirectable methods.
+ */
+ private static final String[] REDIRECT_METHODS = new String[] {
+ HttpGet.METHOD_NAME,
+ HttpHead.METHOD_NAME
+ };
+
+ public DefaultRedirectStrategy() {
+ super();
+ }
+
+ public boolean isRedirected(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws ProtocolException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(response, "HTTP response");
+
+ final int statusCode = response.getStatusLine().getStatusCode();
+ final String method = request.getRequestLine().getMethod();
+ final Header locationHeader = response.getFirstHeader("location");
+ switch (statusCode) {
+ case HttpStatus.SC_MOVED_TEMPORARILY:
+ return isRedirectable(method) && locationHeader != null;
+ case HttpStatus.SC_MOVED_PERMANENTLY:
+ case HttpStatus.SC_TEMPORARY_REDIRECT:
+ return isRedirectable(method);
+ case HttpStatus.SC_SEE_OTHER:
+ return true;
+ default:
+ return false;
+ } //end of switch
+ }
+
+ public URI getLocationURI(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws ProtocolException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(response, "HTTP response");
+ Args.notNull(context, "HTTP context");
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ //get the location header to find out where to redirect to
+ final Header locationHeader = response.getFirstHeader("location");
+ if (locationHeader == null) {
+ // got a redirect response, but no location header
+ throw new ProtocolException(
+ "Received redirect response " + response.getStatusLine()
+ + " but no location header");
+ }
+ final String location = locationHeader.getValue();
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Redirect requested to location '" + location + "'");
+ }
+
+ final RequestConfig config = clientContext.getRequestConfig();
+
+ URI uri = createLocationURI(location);
+
+ // rfc2616 demands the location value be a complete URI
+ // Location = "Location" ":" absoluteURI
+ try {
+ if (!uri.isAbsolute()) {
+ if (!config.isRelativeRedirectsAllowed()) {
+ throw new ProtocolException("Relative redirect location '"
+ + uri + "' not allowed");
+ }
+ // Adjust location URI
+ final HttpHost target = clientContext.getTargetHost();
+ Asserts.notNull(target, "Target host");
+ final URI requestURI = new URI(request.getRequestLine().getUri());
+ final URI absoluteRequestURI = URIUtils.rewriteURI(requestURI, target, false);
+ uri = URIUtils.resolve(absoluteRequestURI, uri);
+ }
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException(ex.getMessage(), ex);
+ }
+
+ RedirectLocations redirectLocations = (RedirectLocations) clientContext.getAttribute(
+ HttpClientContext.REDIRECT_LOCATIONS);
+ if (redirectLocations == null) {
+ redirectLocations = new RedirectLocations();
+ context.setAttribute(HttpClientContext.REDIRECT_LOCATIONS, redirectLocations);
+ }
+ if (!config.isCircularRedirectsAllowed()) {
+ if (redirectLocations.contains(uri)) {
+ throw new CircularRedirectException("Circular redirect to '" + uri + "'");
+ }
+ }
+ redirectLocations.add(uri);
+ return uri;
+ }
+
+ /**
+ * @since 4.1
+ */
+ protected URI createLocationURI(final String location) throws ProtocolException {
+ try {
+ final URIBuilder b = new URIBuilder(new URI(location).normalize());
+ final String host = b.getHost();
+ if (host != null) {
+ b.setHost(host.toLowerCase(Locale.ENGLISH));
+ }
+ final String path = b.getPath();
+ if (TextUtils.isEmpty(path)) {
+ b.setPath("/");
+ }
+ return b.build();
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException("Invalid redirect URI: " + location, ex);
+ }
+ }
+
+ /**
+ * @since 4.2
+ */
+ protected boolean isRedirectable(final String method) {
+ for (final String m: REDIRECT_METHODS) {
+ if (m.equalsIgnoreCase(method)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public HttpUriRequest getRedirect(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws ProtocolException {
+ final URI uri = getLocationURI(request, response, context);
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
+ return new HttpHead(uri);
+ } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
+ return new HttpGet(uri);
+ } else {
+ final int status = response.getStatusLine().getStatusCode();
+ if (status == HttpStatus.SC_TEMPORARY_REDIRECT) {
+ return RequestBuilder.copy(request).setUri(uri).build();
+ } else {
+ return new HttpGet(uri);
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java
new file mode 100644
index 000000000..b49fb7f73
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.URI;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.RedirectHandler;
+import ch.boye.httpclientandroidlib.client.RedirectStrategy;
+import ch.boye.httpclientandroidlib.client.methods.HttpGet;
+import ch.boye.httpclientandroidlib.client.methods.HttpHead;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * @deprecated (4.1) do not use
+ */
+@Immutable
+@Deprecated
+class DefaultRedirectStrategyAdaptor implements RedirectStrategy {
+
+ private final RedirectHandler handler;
+
+ public DefaultRedirectStrategyAdaptor(final RedirectHandler handler) {
+ super();
+ this.handler = handler;
+ }
+
+ public boolean isRedirected(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws ProtocolException {
+ return this.handler.isRedirectRequested(response, context);
+ }
+
+ public HttpUriRequest getRedirect(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws ProtocolException {
+ final URI uri = this.handler.getLocationURI(response, context);
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
+ return new HttpHead(uri);
+ } else {
+ return new HttpGet(uri);
+ }
+ }
+
+ public RedirectHandler getHandler() {
+ return this.handler;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRequestDirector.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRequestDirector.java
new file mode 100644
index 000000000..03d9e1e5f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultRequestDirector.java
@@ -0,0 +1,1150 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.NoHttpResponseException;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthProtocolState;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.auth.UsernamePasswordCredentials;
+import ch.boye.httpclientandroidlib.client.AuthenticationHandler;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler;
+import ch.boye.httpclientandroidlib.client.NonRepeatableRequestException;
+import ch.boye.httpclientandroidlib.client.RedirectException;
+import ch.boye.httpclientandroidlib.client.RedirectHandler;
+import ch.boye.httpclientandroidlib.client.RedirectStrategy;
+import ch.boye.httpclientandroidlib.client.RequestDirector;
+import ch.boye.httpclientandroidlib.client.UserTokenHandler;
+import ch.boye.httpclientandroidlib.client.methods.AbortableHttpRequest;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.client.params.ClientPNames;
+import ch.boye.httpclientandroidlib.client.params.HttpClientParams;
+import ch.boye.httpclientandroidlib.client.protocol.ClientContext;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.conn.BasicManagedEntity;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.BasicRouteDirector;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRouteDirector;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
+import ch.boye.httpclientandroidlib.entity.BufferedHttpEntity;
+import ch.boye.httpclientandroidlib.impl.auth.BasicScheme;
+import ch.boye.httpclientandroidlib.impl.conn.ConnectionShutdownException;
+import ch.boye.httpclientandroidlib.message.BasicHttpRequest;
+import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.params.HttpProtocolParams;
+import ch.boye.httpclientandroidlib.protocol.ExecutionContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * Default implementation of {@link RequestDirector}.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#PROTOCOL_VERSION}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#USE_EXPECT_CONTINUE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#WAIT_FOR_CONTINUE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#USER_AGENT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_LINGER}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_REUSEADDR}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#TCP_NODELAY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#STALE_CONNECTION_CHECK}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#FORCED_ROUTE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#LOCAL_ADDRESS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#DEFAULT_PROXY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#DATE_PATTERNS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#SINGLE_COOKIE_HEADER}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.auth.params.AuthPNames#CREDENTIAL_CHARSET}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#COOKIE_POLICY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#HANDLE_AUTHENTICATION}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#HANDLE_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#MAX_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#ALLOW_CIRCULAR_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#VIRTUAL_HOST}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#DEFAULT_HOST}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#DEFAULT_HEADERS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#CONN_MANAGER_TIMEOUT}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3)
+ */
+@Deprecated
+@NotThreadSafe // e.g. managedConn
+public class DefaultRequestDirector implements RequestDirector {
+
+ public HttpClientAndroidLog log;
+
+ /** The connection manager. */
+ protected final ClientConnectionManager connManager;
+
+ /** The route planner. */
+ protected final HttpRoutePlanner routePlanner;
+
+ /** The connection re-use strategy. */
+ protected final ConnectionReuseStrategy reuseStrategy;
+
+ /** The keep-alive duration strategy. */
+ protected final ConnectionKeepAliveStrategy keepAliveStrategy;
+
+ /** The request executor. */
+ protected final HttpRequestExecutor requestExec;
+
+ /** The HTTP protocol processor. */
+ protected final HttpProcessor httpProcessor;
+
+ /** The request retry handler. */
+ protected final HttpRequestRetryHandler retryHandler;
+
+ /** The redirect handler. */
+ @Deprecated
+ protected final RedirectHandler redirectHandler;
+
+ /** The redirect strategy. */
+ protected final RedirectStrategy redirectStrategy;
+
+ /** The target authentication handler. */
+ @Deprecated
+ protected final AuthenticationHandler targetAuthHandler;
+
+ /** The target authentication handler. */
+ protected final AuthenticationStrategy targetAuthStrategy;
+
+ /** The proxy authentication handler. */
+ @Deprecated
+ protected final AuthenticationHandler proxyAuthHandler;
+
+ /** The proxy authentication handler. */
+ protected final AuthenticationStrategy proxyAuthStrategy;
+
+ /** The user token handler. */
+ protected final UserTokenHandler userTokenHandler;
+
+ /** The HTTP parameters. */
+ protected final HttpParams params;
+
+ /** The currently allocated connection. */
+ protected ManagedClientConnection managedConn;
+
+ protected final AuthState targetAuthState;
+
+ protected final AuthState proxyAuthState;
+
+ private final HttpAuthenticator authenticator;
+
+ private int execCount;
+
+ private int redirectCount;
+
+ private final int maxRedirects;
+
+ private HttpHost virtualHost;
+
+ @Deprecated
+ public DefaultRequestDirector(
+ final HttpRequestExecutor requestExec,
+ final ClientConnectionManager conman,
+ final ConnectionReuseStrategy reustrat,
+ final ConnectionKeepAliveStrategy kastrat,
+ final HttpRoutePlanner rouplan,
+ final HttpProcessor httpProcessor,
+ final HttpRequestRetryHandler retryHandler,
+ final RedirectHandler redirectHandler,
+ final AuthenticationHandler targetAuthHandler,
+ final AuthenticationHandler proxyAuthHandler,
+ final UserTokenHandler userTokenHandler,
+ final HttpParams params) {
+ this(new HttpClientAndroidLog(DefaultRequestDirector.class),
+ requestExec, conman, reustrat, kastrat, rouplan, httpProcessor, retryHandler,
+ new DefaultRedirectStrategyAdaptor(redirectHandler),
+ new AuthenticationStrategyAdaptor(targetAuthHandler),
+ new AuthenticationStrategyAdaptor(proxyAuthHandler),
+ userTokenHandler,
+ params);
+ }
+
+
+ @Deprecated
+ public DefaultRequestDirector(
+ final HttpClientAndroidLog log,
+ final HttpRequestExecutor requestExec,
+ final ClientConnectionManager conman,
+ final ConnectionReuseStrategy reustrat,
+ final ConnectionKeepAliveStrategy kastrat,
+ final HttpRoutePlanner rouplan,
+ final HttpProcessor httpProcessor,
+ final HttpRequestRetryHandler retryHandler,
+ final RedirectStrategy redirectStrategy,
+ final AuthenticationHandler targetAuthHandler,
+ final AuthenticationHandler proxyAuthHandler,
+ final UserTokenHandler userTokenHandler,
+ final HttpParams params) {
+ this(new HttpClientAndroidLog(DefaultRequestDirector.class),
+ requestExec, conman, reustrat, kastrat, rouplan, httpProcessor, retryHandler,
+ redirectStrategy,
+ new AuthenticationStrategyAdaptor(targetAuthHandler),
+ new AuthenticationStrategyAdaptor(proxyAuthHandler),
+ userTokenHandler,
+ params);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public DefaultRequestDirector(
+ final HttpClientAndroidLog log,
+ final HttpRequestExecutor requestExec,
+ final ClientConnectionManager conman,
+ final ConnectionReuseStrategy reustrat,
+ final ConnectionKeepAliveStrategy kastrat,
+ final HttpRoutePlanner rouplan,
+ final HttpProcessor httpProcessor,
+ final HttpRequestRetryHandler retryHandler,
+ final RedirectStrategy redirectStrategy,
+ final AuthenticationStrategy targetAuthStrategy,
+ final AuthenticationStrategy proxyAuthStrategy,
+ final UserTokenHandler userTokenHandler,
+ final HttpParams params) {
+
+ Args.notNull(log, "Log");
+ Args.notNull(requestExec, "Request executor");
+ Args.notNull(conman, "Client connection manager");
+ Args.notNull(reustrat, "Connection reuse strategy");
+ Args.notNull(kastrat, "Connection keep alive strategy");
+ Args.notNull(rouplan, "Route planner");
+ Args.notNull(httpProcessor, "HTTP protocol processor");
+ Args.notNull(retryHandler, "HTTP request retry handler");
+ Args.notNull(redirectStrategy, "Redirect strategy");
+ Args.notNull(targetAuthStrategy, "Target authentication strategy");
+ Args.notNull(proxyAuthStrategy, "Proxy authentication strategy");
+ Args.notNull(userTokenHandler, "User token handler");
+ Args.notNull(params, "HTTP parameters");
+ this.log = log;
+ this.authenticator = new HttpAuthenticator(log);
+ this.requestExec = requestExec;
+ this.connManager = conman;
+ this.reuseStrategy = reustrat;
+ this.keepAliveStrategy = kastrat;
+ this.routePlanner = rouplan;
+ this.httpProcessor = httpProcessor;
+ this.retryHandler = retryHandler;
+ this.redirectStrategy = redirectStrategy;
+ this.targetAuthStrategy = targetAuthStrategy;
+ this.proxyAuthStrategy = proxyAuthStrategy;
+ this.userTokenHandler = userTokenHandler;
+ this.params = params;
+
+ if (redirectStrategy instanceof DefaultRedirectStrategyAdaptor) {
+ this.redirectHandler = ((DefaultRedirectStrategyAdaptor) redirectStrategy).getHandler();
+ } else {
+ this.redirectHandler = null;
+ }
+ if (targetAuthStrategy instanceof AuthenticationStrategyAdaptor) {
+ this.targetAuthHandler = ((AuthenticationStrategyAdaptor) targetAuthStrategy).getHandler();
+ } else {
+ this.targetAuthHandler = null;
+ }
+ if (proxyAuthStrategy instanceof AuthenticationStrategyAdaptor) {
+ this.proxyAuthHandler = ((AuthenticationStrategyAdaptor) proxyAuthStrategy).getHandler();
+ } else {
+ this.proxyAuthHandler = null;
+ }
+
+ this.managedConn = null;
+
+ this.execCount = 0;
+ this.redirectCount = 0;
+ this.targetAuthState = new AuthState();
+ this.proxyAuthState = new AuthState();
+ this.maxRedirects = this.params.getIntParameter(ClientPNames.MAX_REDIRECTS, 100);
+ }
+
+
+ private RequestWrapper wrapRequest(
+ final HttpRequest request) throws ProtocolException {
+ if (request instanceof HttpEntityEnclosingRequest) {
+ return new EntityEnclosingRequestWrapper(
+ (HttpEntityEnclosingRequest) request);
+ } else {
+ return new RequestWrapper(
+ request);
+ }
+ }
+
+
+ protected void rewriteRequestURI(
+ final RequestWrapper request,
+ final HttpRoute route) throws ProtocolException {
+ try {
+
+ URI uri = request.getURI();
+ if (route.getProxyHost() != null && !route.isTunnelled()) {
+ // Make sure the request URI is absolute
+ if (!uri.isAbsolute()) {
+ final HttpHost target = route.getTargetHost();
+ uri = URIUtils.rewriteURI(uri, target, true);
+ } else {
+ uri = URIUtils.rewriteURI(uri);
+ }
+ } else {
+ // Make sure the request URI is relative
+ if (uri.isAbsolute()) {
+ uri = URIUtils.rewriteURI(uri, null, true);
+ } else {
+ uri = URIUtils.rewriteURI(uri);
+ }
+ }
+ request.setURI(uri);
+
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException("Invalid URI: " +
+ request.getRequestLine().getUri(), ex);
+ }
+ }
+
+
+ // non-javadoc, see interface ClientRequestDirector
+ public HttpResponse execute(final HttpHost targetHost, final HttpRequest request,
+ final HttpContext context)
+ throws HttpException, IOException {
+
+ context.setAttribute(ClientContext.TARGET_AUTH_STATE, targetAuthState);
+ context.setAttribute(ClientContext.PROXY_AUTH_STATE, proxyAuthState);
+
+ HttpHost target = targetHost;
+
+ final HttpRequest orig = request;
+ final RequestWrapper origWrapper = wrapRequest(orig);
+ origWrapper.setParams(params);
+ final HttpRoute origRoute = determineRoute(target, origWrapper, context);
+
+ virtualHost = (HttpHost) origWrapper.getParams().getParameter(ClientPNames.VIRTUAL_HOST);
+
+ // HTTPCLIENT-1092 - add the port if necessary
+ if (virtualHost != null && virtualHost.getPort() == -1) {
+ final HttpHost host = (target != null) ? target : origRoute.getTargetHost();
+ final int port = host.getPort();
+ if (port != -1){
+ virtualHost = new HttpHost(virtualHost.getHostName(), port, virtualHost.getSchemeName());
+ }
+ }
+
+ RoutedRequest roureq = new RoutedRequest(origWrapper, origRoute);
+
+ boolean reuse = false;
+ boolean done = false;
+ try {
+ HttpResponse response = null;
+ while (!done) {
+ // In this loop, the RoutedRequest may be replaced by a
+ // followup request and route. The request and route passed
+ // in the method arguments will be replaced. The original
+ // request is still available in 'orig'.
+
+ final RequestWrapper wrapper = roureq.getRequest();
+ final HttpRoute route = roureq.getRoute();
+ response = null;
+
+ // See if we have a user token bound to the execution context
+ Object userToken = context.getAttribute(ClientContext.USER_TOKEN);
+
+ // Allocate connection if needed
+ if (managedConn == null) {
+ final ClientConnectionRequest connRequest = connManager.requestConnection(
+ route, userToken);
+ if (orig instanceof AbortableHttpRequest) {
+ ((AbortableHttpRequest) orig).setConnectionRequest(connRequest);
+ }
+
+ final long timeout = HttpClientParams.getConnectionManagerTimeout(params);
+ try {
+ managedConn = connRequest.getConnection(timeout, TimeUnit.MILLISECONDS);
+ } catch(final InterruptedException interrupted) {
+ Thread.currentThread().interrupt();
+ throw new InterruptedIOException();
+ }
+
+ if (HttpConnectionParams.isStaleCheckingEnabled(params)) {
+ // validate connection
+ if (managedConn.isOpen()) {
+ this.log.debug("Stale connection check");
+ if (managedConn.isStale()) {
+ this.log.debug("Stale connection detected");
+ managedConn.close();
+ }
+ }
+ }
+ }
+
+ if (orig instanceof AbortableHttpRequest) {
+ ((AbortableHttpRequest) orig).setReleaseTrigger(managedConn);
+ }
+
+ try {
+ tryConnect(roureq, context);
+ } catch (final TunnelRefusedException ex) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage());
+ }
+ response = ex.getResponse();
+ break;
+ }
+
+ final String userinfo = wrapper.getURI().getUserInfo();
+ if (userinfo != null) {
+ targetAuthState.update(
+ new BasicScheme(), new UsernamePasswordCredentials(userinfo));
+ }
+
+ // Get target. Even if there's virtual host, we may need the target to set the port.
+ if (virtualHost != null) {
+ target = virtualHost;
+ } else {
+ final URI requestURI = wrapper.getURI();
+ if (requestURI.isAbsolute()) {
+ target = URIUtils.extractHost(requestURI);
+ }
+ }
+ if (target == null) {
+ target = route.getTargetHost();
+ }
+
+ // Reset headers on the request wrapper
+ wrapper.resetHeaders();
+ // Re-write request URI if needed
+ rewriteRequestURI(wrapper, route);
+
+ // Populate the execution context
+ context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, target);
+ context.setAttribute(ClientContext.ROUTE, route);
+ context.setAttribute(ExecutionContext.HTTP_CONNECTION, managedConn);
+
+ // Run request protocol interceptors
+ requestExec.preProcess(wrapper, httpProcessor, context);
+
+ response = tryExecute(roureq, context);
+ if (response == null) {
+ // Need to start over
+ continue;
+ }
+
+ // Run response protocol interceptors
+ response.setParams(params);
+ requestExec.postProcess(response, httpProcessor, context);
+
+
+ // The connection is in or can be brought to a re-usable state.
+ reuse = reuseStrategy.keepAlive(response, context);
+ if (reuse) {
+ // Set the idle duration of this connection
+ final long duration = keepAliveStrategy.getKeepAliveDuration(response, context);
+ if (this.log.isDebugEnabled()) {
+ final String s;
+ if (duration > 0) {
+ s = "for " + duration + " " + TimeUnit.MILLISECONDS;
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection can be kept alive " + s);
+ }
+ managedConn.setIdleDuration(duration, TimeUnit.MILLISECONDS);
+ }
+
+ final RoutedRequest followup = handleResponse(roureq, response, context);
+ if (followup == null) {
+ done = true;
+ } else {
+ if (reuse) {
+ // Make sure the response body is fully consumed, if present
+ final HttpEntity entity = response.getEntity();
+ EntityUtils.consume(entity);
+ // entity consumed above is not an auto-release entity,
+ // need to mark the connection re-usable explicitly
+ managedConn.markReusable();
+ } else {
+ managedConn.close();
+ if (proxyAuthState.getState().compareTo(AuthProtocolState.CHALLENGED) > 0
+ && proxyAuthState.getAuthScheme() != null
+ && proxyAuthState.getAuthScheme().isConnectionBased()) {
+ this.log.debug("Resetting proxy auth state");
+ proxyAuthState.reset();
+ }
+ if (targetAuthState.getState().compareTo(AuthProtocolState.CHALLENGED) > 0
+ && targetAuthState.getAuthScheme() != null
+ && targetAuthState.getAuthScheme().isConnectionBased()) {
+ this.log.debug("Resetting target auth state");
+ targetAuthState.reset();
+ }
+ }
+ // check if we can use the same connection for the followup
+ if (!followup.getRoute().equals(roureq.getRoute())) {
+ releaseConnection();
+ }
+ roureq = followup;
+ }
+
+ if (managedConn != null) {
+ if (userToken == null) {
+ userToken = userTokenHandler.getUserToken(context);
+ context.setAttribute(ClientContext.USER_TOKEN, userToken);
+ }
+ if (userToken != null) {
+ managedConn.setState(userToken);
+ }
+ }
+
+ } // while not done
+
+
+ // check for entity, release connection if possible
+ if ((response == null) || (response.getEntity() == null) ||
+ !response.getEntity().isStreaming()) {
+ // connection not needed and (assumed to be) in re-usable state
+ if (reuse) {
+ managedConn.markReusable();
+ }
+ releaseConnection();
+ } else {
+ // install an auto-release entity
+ HttpEntity entity = response.getEntity();
+ entity = new BasicManagedEntity(entity, managedConn, reuse);
+ response.setEntity(entity);
+ }
+
+ return response;
+
+ } catch (final ConnectionShutdownException ex) {
+ final InterruptedIOException ioex = new InterruptedIOException(
+ "Connection has been shut down");
+ ioex.initCause(ex);
+ throw ioex;
+ } catch (final HttpException ex) {
+ abortConnection();
+ throw ex;
+ } catch (final IOException ex) {
+ abortConnection();
+ throw ex;
+ } catch (final RuntimeException ex) {
+ abortConnection();
+ throw ex;
+ }
+ } // execute
+
+ /**
+ * Establish connection either directly or through a tunnel and retry in case of
+ * a recoverable I/O failure
+ */
+ private void tryConnect(
+ final RoutedRequest req, final HttpContext context) throws HttpException, IOException {
+ final HttpRoute route = req.getRoute();
+ final HttpRequest wrapper = req.getRequest();
+
+ int connectCount = 0;
+ for (;;) {
+ context.setAttribute(ExecutionContext.HTTP_REQUEST, wrapper);
+ // Increment connect count
+ connectCount++;
+ try {
+ if (!managedConn.isOpen()) {
+ managedConn.open(route, context, params);
+ } else {
+ managedConn.setSocketTimeout(HttpConnectionParams.getSoTimeout(params));
+ }
+ establishRoute(route, context);
+ break;
+ } catch (final IOException ex) {
+ try {
+ managedConn.close();
+ } catch (final IOException ignore) {
+ }
+ if (retryHandler.retryRequest(ex, connectCount, context)) {
+ if (this.log.isInfoEnabled()) {
+ this.log.info("I/O exception ("+ ex.getClass().getName() +
+ ") caught when connecting to "
+ + route +
+ ": "
+ + ex.getMessage());
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage(), ex);
+ }
+ this.log.info("Retrying connect to " + route);
+ }
+ } else {
+ throw ex;
+ }
+ }
+ }
+ }
+
+ /**
+ * Execute request and retry in case of a recoverable I/O failure
+ */
+ private HttpResponse tryExecute(
+ final RoutedRequest req, final HttpContext context) throws HttpException, IOException {
+ final RequestWrapper wrapper = req.getRequest();
+ final HttpRoute route = req.getRoute();
+ HttpResponse response = null;
+
+ Exception retryReason = null;
+ for (;;) {
+ // Increment total exec count (with redirects)
+ execCount++;
+ // Increment exec count for this particular request
+ wrapper.incrementExecCount();
+ if (!wrapper.isRepeatable()) {
+ this.log.debug("Cannot retry non-repeatable request");
+ if (retryReason != null) {
+ throw new NonRepeatableRequestException("Cannot retry request " +
+ "with a non-repeatable request entity. The cause lists the " +
+ "reason the original request failed.", retryReason);
+ } else {
+ throw new NonRepeatableRequestException("Cannot retry request " +
+ "with a non-repeatable request entity.");
+ }
+ }
+
+ try {
+ if (!managedConn.isOpen()) {
+ // If we have a direct route to the target host
+ // just re-open connection and re-try the request
+ if (!route.isTunnelled()) {
+ this.log.debug("Reopening the direct connection.");
+ managedConn.open(route, context, params);
+ } else {
+ // otherwise give up
+ this.log.debug("Proxied connection. Need to start over.");
+ break;
+ }
+ }
+
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Attempt " + execCount + " to execute request");
+ }
+ response = requestExec.execute(wrapper, managedConn, context);
+ break;
+
+ } catch (final IOException ex) {
+ this.log.debug("Closing the connection.");
+ try {
+ managedConn.close();
+ } catch (final IOException ignore) {
+ }
+ if (retryHandler.retryRequest(ex, wrapper.getExecCount(), context)) {
+ if (this.log.isInfoEnabled()) {
+ this.log.info("I/O exception ("+ ex.getClass().getName() +
+ ") caught when processing request to "
+ + route +
+ ": "
+ + ex.getMessage());
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage(), ex);
+ }
+ if (this.log.isInfoEnabled()) {
+ this.log.info("Retrying request to " + route);
+ }
+ retryReason = ex;
+ } else {
+ if (ex instanceof NoHttpResponseException) {
+ final NoHttpResponseException updatedex = new NoHttpResponseException(
+ route.getTargetHost().toHostString() + " failed to respond");
+ updatedex.setStackTrace(ex.getStackTrace());
+ throw updatedex;
+ } else {
+ throw ex;
+ }
+ }
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Returns the connection back to the connection manager
+ * and prepares for retrieving a new connection during
+ * the next request.
+ */
+ protected void releaseConnection() {
+ // Release the connection through the ManagedConnection instead of the
+ // ConnectionManager directly. This lets the connection control how
+ // it is released.
+ try {
+ managedConn.releaseConnection();
+ } catch(final IOException ignored) {
+ this.log.debug("IOException releasing connection", ignored);
+ }
+ managedConn = null;
+ }
+
+ /**
+ * Determines the route for a request.
+ * Called by {@link #execute}
+ * to determine the route for either the original or a followup request.
+ *
+ * @param targetHost the target host for the request.
+ * Implementations may accept <code>null</code>
+ * if they can still determine a route, for example
+ * to a default target or by inspecting the request.
+ * @param request the request to execute
+ * @param context the context to use for the execution,
+ * never <code>null</code>
+ *
+ * @return the route the request should take
+ *
+ * @throws HttpException in case of a problem
+ */
+ protected HttpRoute determineRoute(final HttpHost targetHost,
+ final HttpRequest request,
+ final HttpContext context)
+ throws HttpException {
+ return this.routePlanner.determineRoute(
+ targetHost != null ? targetHost : (HttpHost) request.getParams()
+ .getParameter(ClientPNames.DEFAULT_HOST),
+ request, context);
+ }
+
+
+ /**
+ * Establishes the target route.
+ *
+ * @param route the route to establish
+ * @param context the context for the request execution
+ *
+ * @throws HttpException in case of a problem
+ * @throws IOException in case of an IO problem
+ */
+ protected void establishRoute(final HttpRoute route, final HttpContext context)
+ throws HttpException, IOException {
+
+ final HttpRouteDirector rowdy = new BasicRouteDirector();
+ int step;
+ do {
+ final HttpRoute fact = managedConn.getRoute();
+ step = rowdy.nextStep(route, fact);
+
+ switch (step) {
+
+ case HttpRouteDirector.CONNECT_TARGET:
+ case HttpRouteDirector.CONNECT_PROXY:
+ managedConn.open(route, context, this.params);
+ break;
+
+ case HttpRouteDirector.TUNNEL_TARGET: {
+ final boolean secure = createTunnelToTarget(route, context);
+ this.log.debug("Tunnel to target created.");
+ managedConn.tunnelTarget(secure, this.params);
+ } break;
+
+ case HttpRouteDirector.TUNNEL_PROXY: {
+ // The most simple example for this case is a proxy chain
+ // of two proxies, where P1 must be tunnelled to P2.
+ // route: Source -> P1 -> P2 -> Target (3 hops)
+ // fact: Source -> P1 -> Target (2 hops)
+ final int hop = fact.getHopCount()-1; // the hop to establish
+ final boolean secure = createTunnelToProxy(route, hop, context);
+ this.log.debug("Tunnel to proxy created.");
+ managedConn.tunnelProxy(route.getHopTarget(hop),
+ secure, this.params);
+ } break;
+
+
+ case HttpRouteDirector.LAYER_PROTOCOL:
+ managedConn.layerProtocol(context, this.params);
+ break;
+
+ case HttpRouteDirector.UNREACHABLE:
+ throw new HttpException("Unable to establish route: " +
+ "planned = " + route + "; current = " + fact);
+ case HttpRouteDirector.COMPLETE:
+ // do nothing
+ break;
+ default:
+ throw new IllegalStateException("Unknown step indicator "
+ + step + " from RouteDirector.");
+ }
+
+ } while (step > HttpRouteDirector.COMPLETE);
+
+ } // establishConnection
+
+
+ /**
+ * Creates a tunnel to the target server.
+ * The connection must be established to the (last) proxy.
+ * A CONNECT request for tunnelling through the proxy will
+ * be created and sent, the response received and checked.
+ * This method does <i>not</i> update the connection with
+ * information about the tunnel, that is left to the caller.
+ *
+ * @param route the route to establish
+ * @param context the context for request execution
+ *
+ * @return <code>true</code> if the tunnelled route is secure,
+ * <code>false</code> otherwise.
+ * The implementation here always returns <code>false</code>,
+ * but derived classes may override.
+ *
+ * @throws HttpException in case of a problem
+ * @throws IOException in case of an IO problem
+ */
+ protected boolean createTunnelToTarget(final HttpRoute route,
+ final HttpContext context)
+ throws HttpException, IOException {
+
+ final HttpHost proxy = route.getProxyHost();
+ final HttpHost target = route.getTargetHost();
+ HttpResponse response = null;
+
+ for (;;) {
+ if (!this.managedConn.isOpen()) {
+ this.managedConn.open(route, context, this.params);
+ }
+
+ final HttpRequest connect = createConnectRequest(route, context);
+ connect.setParams(this.params);
+
+ // Populate the execution context
+ context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, target);
+ context.setAttribute(ClientContext.ROUTE, route);
+ context.setAttribute(ExecutionContext.HTTP_PROXY_HOST, proxy);
+ context.setAttribute(ExecutionContext.HTTP_CONNECTION, managedConn);
+ context.setAttribute(ExecutionContext.HTTP_REQUEST, connect);
+
+ this.requestExec.preProcess(connect, this.httpProcessor, context);
+
+ response = this.requestExec.execute(connect, this.managedConn, context);
+
+ response.setParams(this.params);
+ this.requestExec.postProcess(response, this.httpProcessor, context);
+
+ final int status = response.getStatusLine().getStatusCode();
+ if (status < 200) {
+ throw new HttpException("Unexpected response to CONNECT request: " +
+ response.getStatusLine());
+ }
+
+ if (HttpClientParams.isAuthenticating(this.params)) {
+ if (this.authenticator.isAuthenticationRequested(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ if (this.authenticator.authenticate(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ // Retry request
+ if (this.reuseStrategy.keepAlive(response, context)) {
+ this.log.debug("Connection kept alive");
+ // Consume response content
+ final HttpEntity entity = response.getEntity();
+ EntityUtils.consume(entity);
+ } else {
+ this.managedConn.close();
+ }
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ final int status = response.getStatusLine().getStatusCode();
+
+ if (status > 299) {
+
+ // Buffer response content
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ response.setEntity(new BufferedHttpEntity(entity));
+ }
+
+ this.managedConn.close();
+ throw new TunnelRefusedException("CONNECT refused by proxy: " +
+ response.getStatusLine(), response);
+ }
+
+ this.managedConn.markReusable();
+
+ // How to decide on security of the tunnelled connection?
+ // The socket factory knows only about the segment to the proxy.
+ // Even if that is secure, the hop to the target may be insecure.
+ // Leave it to derived classes, consider insecure by default here.
+ return false;
+
+ } // createTunnelToTarget
+
+
+
+ /**
+ * Creates a tunnel to an intermediate proxy.
+ * This method is <i>not</i> implemented in this class.
+ * It just throws an exception here.
+ *
+ * @param route the route to establish
+ * @param hop the hop in the route to establish now.
+ * <code>route.getHopTarget(hop)</code>
+ * will return the proxy to tunnel to.
+ * @param context the context for request execution
+ *
+ * @return <code>true</code> if the partially tunnelled connection
+ * is secure, <code>false</code> otherwise.
+ *
+ * @throws HttpException in case of a problem
+ * @throws IOException in case of an IO problem
+ */
+ protected boolean createTunnelToProxy(final HttpRoute route, final int hop,
+ final HttpContext context)
+ throws HttpException, IOException {
+
+ // Have a look at createTunnelToTarget and replicate the parts
+ // you need in a custom derived class. If your proxies don't require
+ // authentication, it is not too hard. But for the stock version of
+ // HttpClient, we cannot make such simplifying assumptions and would
+ // have to include proxy authentication code. The HttpComponents team
+ // is currently not in a position to support rarely used code of this
+ // complexity. Feel free to submit patches that refactor the code in
+ // createTunnelToTarget to facilitate re-use for proxy tunnelling.
+
+ throw new HttpException("Proxy chains are not supported.");
+ }
+
+
+
+ /**
+ * Creates the CONNECT request for tunnelling.
+ * Called by {@link #createTunnelToTarget createTunnelToTarget}.
+ *
+ * @param route the route to establish
+ * @param context the context for request execution
+ *
+ * @return the CONNECT request for tunnelling
+ */
+ protected HttpRequest createConnectRequest(final HttpRoute route,
+ final HttpContext context) {
+ // see RFC 2817, section 5.2 and
+ // INTERNET-DRAFT: Tunneling TCP based protocols through
+ // Web proxy servers
+
+ final HttpHost target = route.getTargetHost();
+
+ final String host = target.getHostName();
+ int port = target.getPort();
+ if (port < 0) {
+ final Scheme scheme = connManager.getSchemeRegistry().
+ getScheme(target.getSchemeName());
+ port = scheme.getDefaultPort();
+ }
+
+ final StringBuilder buffer = new StringBuilder(host.length() + 6);
+ buffer.append(host);
+ buffer.append(':');
+ buffer.append(Integer.toString(port));
+
+ final String authority = buffer.toString();
+ final ProtocolVersion ver = HttpProtocolParams.getVersion(params);
+ final HttpRequest req = new BasicHttpRequest
+ ("CONNECT", authority, ver);
+
+ return req;
+ }
+
+
+ /**
+ * Analyzes a response to check need for a followup.
+ *
+ * @param roureq the request and route.
+ * @param response the response to analayze
+ * @param context the context used for the current request execution
+ *
+ * @return the followup request and route if there is a followup, or
+ * <code>null</code> if the response should be returned as is
+ *
+ * @throws HttpException in case of a problem
+ * @throws IOException in case of an IO problem
+ */
+ protected RoutedRequest handleResponse(final RoutedRequest roureq,
+ final HttpResponse response,
+ final HttpContext context)
+ throws HttpException, IOException {
+
+ final HttpRoute route = roureq.getRoute();
+ final RequestWrapper request = roureq.getRequest();
+
+ final HttpParams params = request.getParams();
+
+ if (HttpClientParams.isAuthenticating(params)) {
+ HttpHost target = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
+ if (target == null) {
+ target = route.getTargetHost();
+ }
+ if (target.getPort() < 0) {
+ final Scheme scheme = connManager.getSchemeRegistry().getScheme(target);
+ target = new HttpHost(target.getHostName(), scheme.getDefaultPort(), target.getSchemeName());
+ }
+
+ final boolean targetAuthRequested = this.authenticator.isAuthenticationRequested(
+ target, response, this.targetAuthStrategy, targetAuthState, context);
+
+ HttpHost proxy = route.getProxyHost();
+ // if proxy is not set use target host instead
+ if (proxy == null) {
+ proxy = route.getTargetHost();
+ }
+ final boolean proxyAuthRequested = this.authenticator.isAuthenticationRequested(
+ proxy, response, this.proxyAuthStrategy, proxyAuthState, context);
+
+ if (targetAuthRequested) {
+ if (this.authenticator.authenticate(target, response,
+ this.targetAuthStrategy, this.targetAuthState, context)) {
+ // Re-try the same request via the same route
+ return roureq;
+ }
+ }
+ if (proxyAuthRequested) {
+ if (this.authenticator.authenticate(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ // Re-try the same request via the same route
+ return roureq;
+ }
+ }
+ }
+
+ if (HttpClientParams.isRedirecting(params) &&
+ this.redirectStrategy.isRedirected(request, response, context)) {
+
+ if (redirectCount >= maxRedirects) {
+ throw new RedirectException("Maximum redirects ("
+ + maxRedirects + ") exceeded");
+ }
+ redirectCount++;
+
+ // Virtual host cannot be used any longer
+ virtualHost = null;
+
+ final HttpUriRequest redirect = redirectStrategy.getRedirect(request, response, context);
+ final HttpRequest orig = request.getOriginal();
+ redirect.setHeaders(orig.getAllHeaders());
+
+ final URI uri = redirect.getURI();
+ final HttpHost newTarget = URIUtils.extractHost(uri);
+ if (newTarget == null) {
+ throw new ProtocolException("Redirect URI does not specify a valid host name: " + uri);
+ }
+
+ // Reset auth states if redirecting to another host
+ if (!route.getTargetHost().equals(newTarget)) {
+ this.log.debug("Resetting target auth state");
+ targetAuthState.reset();
+ final AuthScheme authScheme = proxyAuthState.getAuthScheme();
+ if (authScheme != null && authScheme.isConnectionBased()) {
+ this.log.debug("Resetting proxy auth state");
+ proxyAuthState.reset();
+ }
+ }
+
+ final RequestWrapper wrapper = wrapRequest(redirect);
+ wrapper.setParams(params);
+
+ final HttpRoute newRoute = determineRoute(newTarget, wrapper, context);
+ final RoutedRequest newRequest = new RoutedRequest(wrapper, newRoute);
+
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Redirecting to '" + uri + "' via " + newRoute);
+ }
+
+ return newRequest;
+ }
+
+ return null;
+ } // handleResponse
+
+
+ /**
+ * Shuts down the connection.
+ * This method is called from a <code>catch</code> block in
+ * {@link #execute execute} during exception handling.
+ */
+ private void abortConnection() {
+ final ManagedClientConnection mcc = managedConn;
+ if (mcc != null) {
+ // we got here as the result of an exception
+ // no response will be returned, release the connection
+ managedConn = null;
+ try {
+ mcc.abortConnection();
+ } catch (final IOException ex) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage(), ex);
+ }
+ }
+ // ensure the connection manager properly releases this connection
+ try {
+ mcc.releaseConnection();
+ } catch(final IOException ignored) {
+ this.log.debug("Error releasing connection", ignored);
+ }
+ }
+ } // abortConnection
+
+
+} // class DefaultClientRequestDirector
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultServiceUnavailableRetryStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultServiceUnavailableRetryStrategy.java
new file mode 100644
index 000000000..8e7279aab
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultServiceUnavailableRetryStrategy.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.ServiceUnavailableRetryStrategy;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of the {@link ServiceUnavailableRetryStrategy} interface.
+ * that retries <code>503</code> (Service Unavailable) responses for a fixed number of times
+ * at a fixed interval.
+ *
+ * @since 4.2
+ */
+@Immutable
+public class DefaultServiceUnavailableRetryStrategy implements ServiceUnavailableRetryStrategy {
+
+ /**
+ * Maximum number of allowed retries if the server responds with a HTTP code
+ * in our retry code list. Default value is 1.
+ */
+ private final int maxRetries;
+
+ /**
+ * Retry interval between subsequent requests, in milliseconds. Default
+ * value is 1 second.
+ */
+ private final long retryInterval;
+
+ public DefaultServiceUnavailableRetryStrategy(final int maxRetries, final int retryInterval) {
+ super();
+ Args.positive(maxRetries, "Max retries");
+ Args.positive(retryInterval, "Retry interval");
+ this.maxRetries = maxRetries;
+ this.retryInterval = retryInterval;
+ }
+
+ public DefaultServiceUnavailableRetryStrategy() {
+ this(1, 1000);
+ }
+
+ public boolean retryRequest(final HttpResponse response, final int executionCount, final HttpContext context) {
+ return executionCount <= maxRetries &&
+ response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
+ }
+
+ public long getRetryInterval() {
+ return retryInterval;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java
new file mode 100644
index 000000000..a2a57e1d5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java
@@ -0,0 +1,91 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.List;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.MalformedChallengeException;
+import ch.boye.httpclientandroidlib.auth.params.AuthPNames;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default {@link ch.boye.httpclientandroidlib.client.AuthenticationHandler} implementation
+ * for target host authentication.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link TargetAuthenticationStrategy}
+ */
+@Deprecated
+@Immutable
+public class DefaultTargetAuthenticationHandler extends AbstractAuthenticationHandler {
+
+ public DefaultTargetAuthenticationHandler() {
+ super();
+ }
+
+ public boolean isAuthenticationRequested(
+ final HttpResponse response,
+ final HttpContext context) {
+ Args.notNull(response, "HTTP response");
+ final int status = response.getStatusLine().getStatusCode();
+ return status == HttpStatus.SC_UNAUTHORIZED;
+ }
+
+ public Map<String, Header> getChallenges(
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ Args.notNull(response, "HTTP response");
+ final Header[] headers = response.getHeaders(AUTH.WWW_AUTH);
+ return parseChallenges(headers);
+ }
+
+ @Override
+ protected List<String> getAuthPreferences(
+ final HttpResponse response,
+ final HttpContext context) {
+ @SuppressWarnings("unchecked")
+ final
+ List<String> authpref = (List<String>) response.getParams().getParameter(
+ AuthPNames.TARGET_AUTH_PREF);
+ if (authpref != null) {
+ return authpref;
+ } else {
+ return super.getAuthPreferences(response, context);
+ }
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultUserTokenHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultUserTokenHandler.java
new file mode 100644
index 000000000..c6d2a8daa
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/DefaultUserTokenHandler.java
@@ -0,0 +1,101 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.security.Principal;
+
+import javax.net.ssl.SSLSession;
+
+import ch.boye.httpclientandroidlib.HttpConnection;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.client.UserTokenHandler;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Default implementation of {@link UserTokenHandler}. This class will use
+ * an instance of {@link Principal} as a state object for HTTP connections,
+ * if it can be obtained from the given execution context. This helps ensure
+ * persistent connections created with a particular user identity within
+ * a particular security context can be reused by the same user only.
+ * <p>
+ * DefaultUserTokenHandler will use the user principle of connection
+ * based authentication schemes such as NTLM or that of the SSL session
+ * with the client authentication turned on. If both are unavailable,
+ * <code>null</code> token will be returned.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class DefaultUserTokenHandler implements UserTokenHandler {
+
+ public static final DefaultUserTokenHandler INSTANCE = new DefaultUserTokenHandler();
+
+ public Object getUserToken(final HttpContext context) {
+
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+
+ Principal userPrincipal = null;
+
+ final AuthState targetAuthState = clientContext.getTargetAuthState();
+ if (targetAuthState != null) {
+ userPrincipal = getAuthPrincipal(targetAuthState);
+ if (userPrincipal == null) {
+ final AuthState proxyAuthState = clientContext.getProxyAuthState();
+ userPrincipal = getAuthPrincipal(proxyAuthState);
+ }
+ }
+
+ if (userPrincipal == null) {
+ final HttpConnection conn = clientContext.getConnection();
+ if (conn.isOpen() && conn instanceof ManagedHttpClientConnection) {
+ final SSLSession sslsession = ((ManagedHttpClientConnection) conn).getSSLSession();
+ if (sslsession != null) {
+ userPrincipal = sslsession.getLocalPrincipal();
+ }
+ }
+ }
+
+ return userPrincipal;
+ }
+
+ private static Principal getAuthPrincipal(final AuthState authState) {
+ final AuthScheme scheme = authState.getAuthScheme();
+ if (scheme != null && scheme.isComplete() && scheme.isConnectionBased()) {
+ final Credentials creds = authState.getCredentials();
+ if (creds != null) {
+ return creds.getUserPrincipal();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java
new file mode 100644
index 000000000..45fbbe0a6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java
@@ -0,0 +1,113 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * A wrapper class for {@link HttpEntityEnclosingRequest}s that can
+ * be used to change properties of the current request without
+ * modifying the original object.
+ * </p>
+ * This class is also capable of resetting the request headers to
+ * the state of the original request.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) do not use.
+ */
+@Deprecated
+@NotThreadSafe // e.g. [gs]etEntity()
+public class EntityEnclosingRequestWrapper extends RequestWrapper
+ implements HttpEntityEnclosingRequest {
+
+ private HttpEntity entity;
+ private boolean consumed;
+
+ public EntityEnclosingRequestWrapper(final HttpEntityEnclosingRequest request)
+ throws ProtocolException {
+ super(request);
+ setEntity(request.getEntity());
+ }
+
+ public HttpEntity getEntity() {
+ return this.entity;
+ }
+
+ public void setEntity(final HttpEntity entity) {
+ this.entity = entity != null ? new EntityWrapper(entity) : null;
+ this.consumed = false;
+ }
+
+ public boolean expectContinue() {
+ final Header expect = getFirstHeader(HTTP.EXPECT_DIRECTIVE);
+ return expect != null && HTTP.EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue());
+ }
+
+ @Override
+ public boolean isRepeatable() {
+ return this.entity == null || this.entity.isRepeatable() || !this.consumed;
+ }
+
+ class EntityWrapper extends HttpEntityWrapper {
+
+ EntityWrapper(final HttpEntity entity) {
+ super(entity);
+ }
+
+ @Override
+ public void consumeContent() throws IOException {
+ consumed = true;
+ super.consumeContent();
+ }
+
+ @Override
+ public InputStream getContent() throws IOException {
+ consumed = true;
+ return super.getContent();
+ }
+
+ @Override
+ public void writeTo(final OutputStream outstream) throws IOException {
+ consumed = true;
+ super.writeTo(outstream);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionMetrics.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionMetrics.java
new file mode 100644
index 000000000..888e7e3a5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionMetrics.java
@@ -0,0 +1,156 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Collection of different counters used to gather metrics for {@link FutureRequestExecutionService}.
+ */
+public final class FutureRequestExecutionMetrics {
+
+ private final AtomicLong activeConnections = new AtomicLong();
+ private final AtomicLong scheduledConnections = new AtomicLong();
+ private final DurationCounter successfulConnections = new DurationCounter();
+ private final DurationCounter failedConnections = new DurationCounter();
+ private final DurationCounter requests = new DurationCounter();
+ private final DurationCounter tasks = new DurationCounter();
+
+ FutureRequestExecutionMetrics() {
+ }
+
+ AtomicLong getActiveConnections() {
+ return activeConnections;
+ }
+
+ AtomicLong getScheduledConnections() {
+ return scheduledConnections;
+ }
+
+ DurationCounter getSuccessfulConnections() {
+ return successfulConnections;
+ }
+
+ DurationCounter getFailedConnections() {
+ return failedConnections;
+ }
+
+ DurationCounter getRequests() {
+ return requests;
+ }
+
+ DurationCounter getTasks() {
+ return tasks;
+ }
+
+ public long getActiveConnectionCount() {
+ return activeConnections.get();
+ }
+
+ public long getScheduledConnectionCount() {
+ return scheduledConnections.get();
+ }
+
+ public long getSuccessfulConnectionCount() {
+ return successfulConnections.count();
+ }
+
+ public long getSuccessfulConnectionAverageDuration() {
+ return successfulConnections.averageDuration();
+ }
+
+ public long getFailedConnectionCount() {
+ return failedConnections.count();
+ }
+
+ public long getFailedConnectionAverageDuration() {
+ return failedConnections.averageDuration();
+ }
+
+ public long getRequestCount() {
+ return requests.count();
+ }
+
+ public long getRequestAverageDuration() {
+ return requests.averageDuration();
+ }
+
+ public long getTaskCount() {
+ return tasks.count();
+ }
+
+ public long getTaskAverageDuration() {
+ return tasks.averageDuration();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[activeConnections=").append(activeConnections)
+ .append(", scheduledConnections=").append(scheduledConnections)
+ .append(", successfulConnections=").append(successfulConnections)
+ .append(", failedConnections=").append(failedConnections)
+ .append(", requests=").append(requests)
+ .append(", tasks=").append(tasks)
+ .append("]");
+ return builder.toString();
+ }
+
+ /**
+ * A counter that can measure duration and number of events.
+ */
+ static class DurationCounter {
+
+ private final AtomicLong count = new AtomicLong(0);
+ private final AtomicLong cumulativeDuration = new AtomicLong(0);
+
+ public void increment(final long startTime) {
+ count.incrementAndGet();
+ cumulativeDuration.addAndGet(System.currentTimeMillis() - startTime);
+ }
+
+ public long count() {
+ return count.get();
+ }
+
+ public long averageDuration() {
+ final long counter = count.get();
+ return counter > 0 ? cumulativeDuration.get() / counter : 0;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[count=").append(count())
+ .append(", averageDuration=").append(averageDuration())
+ .append("]");
+ return builder.toString();
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionService.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionService.java
new file mode 100644
index 000000000..26fa9dba3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/FutureRequestExecutionService.java
@@ -0,0 +1,142 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.HttpClient;
+import ch.boye.httpclientandroidlib.client.ResponseHandler;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.concurrent.FutureCallback;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * HttpAsyncClientWithFuture wraps calls to execute with a {@link HttpRequestFutureTask}
+ * and schedules them using the provided executor service. Scheduled calls may be cancelled.
+ */
+@ThreadSafe
+public class FutureRequestExecutionService implements Closeable {
+
+ private final HttpClient httpclient;
+ private final ExecutorService executorService;
+ private final FutureRequestExecutionMetrics metrics = new FutureRequestExecutionMetrics();
+ private final AtomicBoolean closed = new AtomicBoolean(false);
+
+ /**
+ * Create a new FutureRequestExecutionService.
+ *
+ * @param httpclient
+ * you should tune your httpclient instance to match your needs. You should
+ * align the max number of connections in the pool and the number of threads
+ * in the executor; it doesn't make sense to have more threads than connections
+ * and if you have less connections than threads, the threads will just end up
+ * blocking on getting a connection from the pool.
+ * @param executorService
+ * any executorService will do here. E.g.
+ * {@link java.util.concurrent.Executors#newFixedThreadPool(int)}
+ */
+ public FutureRequestExecutionService(
+ final HttpClient httpclient,
+ final ExecutorService executorService) {
+ this.httpclient = httpclient;
+ this.executorService = executorService;
+ }
+
+ /**
+ * Schedule a request for execution.
+ *
+ * @param <T>
+ *
+ * @param request
+ * request to execute
+ * @param responseHandler
+ * handler that will process the response.
+ * @return HttpAsyncClientFutureTask for the scheduled request.
+ * @throws InterruptedException
+ */
+ public <T> HttpRequestFutureTask<T> execute(
+ final HttpUriRequest request,
+ final HttpContext context,
+ final ResponseHandler<T> responseHandler) {
+ return execute(request, context, responseHandler, null);
+ }
+
+ /**
+ * Schedule a request for execution.
+ *
+ * @param <T>
+ *
+ * @param request
+ * request to execute
+ * @param context
+ * optional context; use null if not needed.
+ * @param responseHandler
+ * handler that will process the response.
+ * @param callback
+ * callback handler that will be called when the request is scheduled,
+ * started, completed, failed, or cancelled.
+ * @return HttpAsyncClientFutureTask for the scheduled request.
+ * @throws InterruptedException
+ */
+ public <T> HttpRequestFutureTask<T> execute(
+ final HttpUriRequest request,
+ final HttpContext context,
+ final ResponseHandler<T> responseHandler,
+ final FutureCallback<T> callback) {
+ if(closed.get()) {
+ throw new IllegalStateException("Close has been called on this httpclient instance.");
+ }
+ metrics.getScheduledConnections().incrementAndGet();
+ final HttpRequestTaskCallable<T> callable = new HttpRequestTaskCallable<T>(
+ httpclient, request, context, responseHandler, callback, metrics);
+ final HttpRequestFutureTask<T> httpRequestFutureTask = new HttpRequestFutureTask<T>(
+ request, callable);
+ executorService.execute(httpRequestFutureTask);
+
+ return httpRequestFutureTask;
+ }
+
+ /**
+ * @return metrics gathered for this instance.
+ * @see FutureRequestExecutionMetrics
+ */
+ public FutureRequestExecutionMetrics metrics() {
+ return metrics;
+ }
+
+ public void close() throws IOException {
+ closed.set(true);
+ executorService.shutdownNow();
+ if (httpclient instanceof Closeable) {
+ ((Closeable) httpclient).close();
+ }
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpAuthenticator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpAuthenticator.java
new file mode 100644
index 000000000..745ae4735
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpAuthenticator.java
@@ -0,0 +1,61 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * @deprecated (4.3) reserved for internal use.
+ *
+ */
+@Deprecated
+public class HttpAuthenticator extends ch.boye.httpclientandroidlib.impl.auth.HttpAuthenticator {
+
+ public HttpAuthenticator(final HttpClientAndroidLog log) {
+ super(log);
+ }
+
+ public HttpAuthenticator() {
+ super();
+ }
+
+ public boolean authenticate (
+ final HttpHost host,
+ final HttpResponse response,
+ final AuthenticationStrategy authStrategy,
+ final AuthState authState,
+ final HttpContext context) {
+ return handleAuthChallenge(host, response, authStrategy, authState, context);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClientBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClientBuilder.java
new file mode 100644
index 000000000..00313e668
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClientBuilder.java
@@ -0,0 +1,954 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.Closeable;
+import java.net.ProxySelector;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.client.BackoffManager;
+import ch.boye.httpclientandroidlib.client.ConnectionBackoffStrategy;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler;
+import ch.boye.httpclientandroidlib.client.RedirectStrategy;
+import ch.boye.httpclientandroidlib.client.ServiceUnavailableRetryStrategy;
+import ch.boye.httpclientandroidlib.client.UserTokenHandler;
+import ch.boye.httpclientandroidlib.client.config.AuthSchemes;
+import ch.boye.httpclientandroidlib.client.config.CookieSpecs;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.protocol.RequestAcceptEncoding;
+import ch.boye.httpclientandroidlib.client.protocol.RequestAddCookies;
+import ch.boye.httpclientandroidlib.client.protocol.RequestAuthCache;
+import ch.boye.httpclientandroidlib.client.protocol.RequestClientConnControl;
+import ch.boye.httpclientandroidlib.client.protocol.RequestDefaultHeaders;
+import ch.boye.httpclientandroidlib.client.protocol.RequestExpectContinue;
+import ch.boye.httpclientandroidlib.client.protocol.ResponseContentEncoding;
+import ch.boye.httpclientandroidlib.client.protocol.ResponseProcessCookies;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.config.RegistryBuilder;
+import ch.boye.httpclientandroidlib.config.SocketConfig;
+import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.conn.socket.ConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.socket.PlainConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.ssl.SSLConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.ssl.SSLContexts;
+import ch.boye.httpclientandroidlib.conn.ssl.X509HostnameVerifier;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.NoConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.auth.BasicSchemeFactory;
+import ch.boye.httpclientandroidlib.impl.auth.DigestSchemeFactory;
+/* KerberosSchemeFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.impl.auth.NTLMSchemeFactory;
+/* SPNegoSchemeFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.impl.conn.DefaultProxyRoutePlanner;
+import ch.boye.httpclientandroidlib.impl.conn.DefaultRoutePlanner;
+import ch.boye.httpclientandroidlib.impl.conn.DefaultSchemePortResolver;
+import ch.boye.httpclientandroidlib.impl.conn.PoolingHttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.impl.conn.SystemDefaultRoutePlanner;
+import ch.boye.httpclientandroidlib.impl.cookie.BestMatchSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.BrowserCompatSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.IgnoreSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.NetscapeDraftSpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.RFC2109SpecFactory;
+import ch.boye.httpclientandroidlib.impl.cookie.RFC2965SpecFactory;
+import ch.boye.httpclientandroidlib.impl.execchain.BackoffStrategyExec;
+import ch.boye.httpclientandroidlib.impl.execchain.ClientExecChain;
+import ch.boye.httpclientandroidlib.impl.execchain.MainClientExec;
+import ch.boye.httpclientandroidlib.impl.execchain.ProtocolExec;
+import ch.boye.httpclientandroidlib.impl.execchain.RedirectExec;
+import ch.boye.httpclientandroidlib.impl.execchain.RetryExec;
+import ch.boye.httpclientandroidlib.impl.execchain.ServiceUnavailableRetryExec;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessorBuilder;
+import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor;
+import ch.boye.httpclientandroidlib.protocol.RequestContent;
+import ch.boye.httpclientandroidlib.protocol.RequestTargetHost;
+import ch.boye.httpclientandroidlib.protocol.RequestUserAgent;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+import ch.boye.httpclientandroidlib.util.VersionInfo;
+
+/**
+ * Builder for {@link CloseableHttpClient} instances.
+ * <p/>
+ * When a particular component is not explicitly this class will
+ * use its default implementation. System properties will be taken
+ * into account when configuring the default implementations when
+ * {@link #useSystemProperties()} method is called prior to calling
+ * {@link #build()}.
+ * <ul>
+ * <li>ssl.TrustManagerFactory.algorithm</li>
+ * <li>javax.net.ssl.trustStoreType</li>
+ * <li>javax.net.ssl.trustStore</li>
+ * <li>javax.net.ssl.trustStoreProvider</li>
+ * <li>javax.net.ssl.trustStorePassword</li>
+ * <li>ssl.KeyManagerFactory.algorithm</li>
+ * <li>javax.net.ssl.keyStoreType</li>
+ * <li>javax.net.ssl.keyStore</li>
+ * <li>javax.net.ssl.keyStoreProvider</li>
+ * <li>javax.net.ssl.keyStorePassword</li>
+ * <li>https.protocols</li>
+ * <li>https.cipherSuites</li>
+ * <li>http.proxyHost</li>
+ * <li>http.proxyPort</li>
+ * <li>http.nonProxyHosts</li>
+ * <li>http.keepAlive</li>
+ * <li>http.maxConnections</li>
+ * <li>http.agent</li>
+ * </ul>
+ * <p/>
+ * Please note that some settings used by this class can be mutually
+ * exclusive and may not apply when building {@link CloseableHttpClient}
+ * instances.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class HttpClientBuilder {
+
+ private HttpRequestExecutor requestExec;
+ private X509HostnameVerifier hostnameVerifier;
+ private LayeredConnectionSocketFactory sslSocketFactory;
+ private SSLContext sslcontext;
+ private HttpClientConnectionManager connManager;
+ private SchemePortResolver schemePortResolver;
+ private ConnectionReuseStrategy reuseStrategy;
+ private ConnectionKeepAliveStrategy keepAliveStrategy;
+ private AuthenticationStrategy targetAuthStrategy;
+ private AuthenticationStrategy proxyAuthStrategy;
+ private UserTokenHandler userTokenHandler;
+ private HttpProcessor httpprocessor;
+
+ private LinkedList<HttpRequestInterceptor> requestFirst;
+ private LinkedList<HttpRequestInterceptor> requestLast;
+ private LinkedList<HttpResponseInterceptor> responseFirst;
+ private LinkedList<HttpResponseInterceptor> responseLast;
+
+ private HttpRequestRetryHandler retryHandler;
+ private HttpRoutePlanner routePlanner;
+ private RedirectStrategy redirectStrategy;
+ private ConnectionBackoffStrategy connectionBackoffStrategy;
+ private BackoffManager backoffManager;
+ private ServiceUnavailableRetryStrategy serviceUnavailStrategy;
+ private Lookup<AuthSchemeProvider> authSchemeRegistry;
+ private Lookup<CookieSpecProvider> cookieSpecRegistry;
+ private CookieStore cookieStore;
+ private CredentialsProvider credentialsProvider;
+ private String userAgent;
+ private HttpHost proxy;
+ private Collection<? extends Header> defaultHeaders;
+ private SocketConfig defaultSocketConfig;
+ private ConnectionConfig defaultConnectionConfig;
+ private RequestConfig defaultRequestConfig;
+
+ private boolean systemProperties;
+ private boolean redirectHandlingDisabled;
+ private boolean automaticRetriesDisabled;
+ private boolean contentCompressionDisabled;
+ private boolean cookieManagementDisabled;
+ private boolean authCachingDisabled;
+ private boolean connectionStateDisabled;
+
+ private int maxConnTotal = 0;
+ private int maxConnPerRoute = 0;
+
+ private List<Closeable> closeables;
+
+ static final String DEFAULT_USER_AGENT;
+ static {
+ final VersionInfo vi = VersionInfo.loadVersionInfo
+ ("ch.boye.httpclientandroidlib.client", HttpClientBuilder.class.getClassLoader());
+ final String release = (vi != null) ?
+ vi.getRelease() : VersionInfo.UNAVAILABLE;
+ DEFAULT_USER_AGENT = "Apache-HttpClient/" + release + " (java 1.5)";
+ }
+
+ public static HttpClientBuilder create() {
+ return new HttpClientBuilder();
+ }
+
+ protected HttpClientBuilder() {
+ super();
+ }
+
+ /**
+ * Assigns {@link HttpRequestExecutor} instance.
+ */
+ public final HttpClientBuilder setRequestExecutor(final HttpRequestExecutor requestExec) {
+ this.requestExec = requestExec;
+ return this;
+ }
+
+ /**
+ * Assigns {@link X509HostnameVerifier} instance.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setConnectionManager(
+ * ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
+ * ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory)} methods.
+ */
+ public final HttpClientBuilder setHostnameVerifier(final X509HostnameVerifier hostnameVerifier) {
+ this.hostnameVerifier = hostnameVerifier;
+ return this;
+ }
+
+ /**
+ * Assigns {@link SSLContext} instance.
+ * <p/>
+ * <p/>
+ * Please note this value can be overridden by the {@link #setConnectionManager(
+ * ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
+ * ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory)} methods.
+ */
+ public final HttpClientBuilder setSslcontext(final SSLContext sslcontext) {
+ this.sslcontext = sslcontext;
+ return this;
+ }
+
+ /**
+ * Assigns {@link LayeredConnectionSocketFactory} instance.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setConnectionManager(
+ * ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager)} method.
+ */
+ public final HttpClientBuilder setSSLSocketFactory(
+ final LayeredConnectionSocketFactory sslSocketFactory) {
+ this.sslSocketFactory = sslSocketFactory;
+ return this;
+ }
+
+ /**
+ * Assigns maximum total connection value.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setConnectionManager(
+ * ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager)} method.
+ */
+ public final HttpClientBuilder setMaxConnTotal(final int maxConnTotal) {
+ this.maxConnTotal = maxConnTotal;
+ return this;
+ }
+
+ /**
+ * Assigns maximum connection per route value.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setConnectionManager(
+ * ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager)} method.
+ */
+ public final HttpClientBuilder setMaxConnPerRoute(final int maxConnPerRoute) {
+ this.maxConnPerRoute = maxConnPerRoute;
+ return this;
+ }
+
+ /**
+ * Assigns default {@link SocketConfig}.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setConnectionManager(
+ * ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager)} method.
+ */
+ public final HttpClientBuilder setDefaultSocketConfig(final SocketConfig config) {
+ this.defaultSocketConfig = config;
+ return this;
+ }
+
+ /**
+ * Assigns default {@link ConnectionConfig}.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setConnectionManager(
+ * ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager)} method.
+ */
+ public final HttpClientBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
+ this.defaultConnectionConfig = config;
+ return this;
+ }
+
+ /**
+ * Assigns {@link HttpClientConnectionManager} instance.
+ */
+ public final HttpClientBuilder setConnectionManager(
+ final HttpClientConnectionManager connManager) {
+ this.connManager = connManager;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ConnectionReuseStrategy} instance.
+ */
+ public final HttpClientBuilder setConnectionReuseStrategy(
+ final ConnectionReuseStrategy reuseStrategy) {
+ this.reuseStrategy = reuseStrategy;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ConnectionKeepAliveStrategy} instance.
+ */
+ public final HttpClientBuilder setKeepAliveStrategy(
+ final ConnectionKeepAliveStrategy keepAliveStrategy) {
+ this.keepAliveStrategy = keepAliveStrategy;
+ return this;
+ }
+
+ /**
+ * Assigns {@link AuthenticationStrategy} instance for proxy
+ * authentication.
+ */
+ public final HttpClientBuilder setTargetAuthenticationStrategy(
+ final AuthenticationStrategy targetAuthStrategy) {
+ this.targetAuthStrategy = targetAuthStrategy;
+ return this;
+ }
+
+ /**
+ * Assigns {@link AuthenticationStrategy} instance for target
+ * host authentication.
+ */
+ public final HttpClientBuilder setProxyAuthenticationStrategy(
+ final AuthenticationStrategy proxyAuthStrategy) {
+ this.proxyAuthStrategy = proxyAuthStrategy;
+ return this;
+ }
+
+ /**
+ * Assigns {@link UserTokenHandler} instance.
+ * <p/>
+ * Please note this value can be overridden by the {@link #disableConnectionState()}
+ * method.
+ */
+ public final HttpClientBuilder setUserTokenHandler(final UserTokenHandler userTokenHandler) {
+ this.userTokenHandler = userTokenHandler;
+ return this;
+ }
+
+ /**
+ * Disables connection state tracking.
+ */
+ public final HttpClientBuilder disableConnectionState() {
+ connectionStateDisabled = true;
+ return this;
+ }
+
+ /**
+ * Assigns {@link SchemePortResolver} instance.
+ */
+ public final HttpClientBuilder setSchemePortResolver(
+ final SchemePortResolver schemePortResolver) {
+ this.schemePortResolver = schemePortResolver;
+ return this;
+ }
+
+ /**
+ * Assigns <tt>User-Agent</tt> value.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder setUserAgent(final String userAgent) {
+ this.userAgent = userAgent;
+ return this;
+ }
+
+ /**
+ * Assigns default request header values.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder setDefaultHeaders(final Collection<? extends Header> defaultHeaders) {
+ this.defaultHeaders = defaultHeaders;
+ return this;
+ }
+
+ /**
+ * Adds this protocol interceptor to the head of the protocol processing list.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder addInterceptorFirst(final HttpResponseInterceptor itcp) {
+ if (itcp == null) {
+ return this;
+ }
+ if (responseFirst == null) {
+ responseFirst = new LinkedList<HttpResponseInterceptor>();
+ }
+ responseFirst.addFirst(itcp);
+ return this;
+ }
+
+ /**
+ * Adds this protocol interceptor to the tail of the protocol processing list.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder addInterceptorLast(final HttpResponseInterceptor itcp) {
+ if (itcp == null) {
+ return this;
+ }
+ if (responseLast == null) {
+ responseLast = new LinkedList<HttpResponseInterceptor>();
+ }
+ responseLast.addLast(itcp);
+ return this;
+ }
+
+ /**
+ * Adds this protocol interceptor to the head of the protocol processing list.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder addInterceptorFirst(final HttpRequestInterceptor itcp) {
+ if (itcp == null) {
+ return this;
+ }
+ if (requestFirst == null) {
+ requestFirst = new LinkedList<HttpRequestInterceptor>();
+ }
+ requestFirst.addFirst(itcp);
+ return this;
+ }
+
+ /**
+ * Adds this protocol interceptor to the tail of the protocol processing list.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder addInterceptorLast(final HttpRequestInterceptor itcp) {
+ if (itcp == null) {
+ return this;
+ }
+ if (requestLast == null) {
+ requestLast = new LinkedList<HttpRequestInterceptor>();
+ }
+ requestLast.addLast(itcp);
+ return this;
+ }
+
+ /**
+ * Disables state (cookie) management.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder disableCookieManagement() {
+ this.cookieManagementDisabled = true;
+ return this;
+ }
+
+ /**
+ * Disables automatic content decompression.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder disableContentCompression() {
+ contentCompressionDisabled = true;
+ return this;
+ }
+
+ /**
+ * Disables authentication scheme caching.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setHttpProcessor(
+ * ch.boye.httpclientandroidlib.protocol.HttpProcessor)} method.
+ */
+ public final HttpClientBuilder disableAuthCaching() {
+ this.authCachingDisabled = true;
+ return this;
+ }
+
+ /**
+ * Assigns {@link HttpProcessor} instance.
+ */
+ public final HttpClientBuilder setHttpProcessor(final HttpProcessor httpprocessor) {
+ this.httpprocessor = httpprocessor;
+ return this;
+ }
+
+ /**
+ * Assigns {@link HttpRequestRetryHandler} instance.
+ * <p/>
+ * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
+ * method.
+ */
+ public final HttpClientBuilder setRetryHandler(final HttpRequestRetryHandler retryHandler) {
+ this.retryHandler = retryHandler;
+ return this;
+ }
+
+ /**
+ * Disables automatic request recovery and re-execution.
+ */
+ public final HttpClientBuilder disableAutomaticRetries() {
+ automaticRetriesDisabled = true;
+ return this;
+ }
+
+ /**
+ * Assigns default proxy value.
+ * <p/>
+ * Please note this value can be overridden by the {@link #setRoutePlanner(
+ * ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner)} method.
+ */
+ public final HttpClientBuilder setProxy(final HttpHost proxy) {
+ this.proxy = proxy;
+ return this;
+ }
+
+ /**
+ * Assigns {@link HttpRoutePlanner} instance.
+ */
+ public final HttpClientBuilder setRoutePlanner(final HttpRoutePlanner routePlanner) {
+ this.routePlanner = routePlanner;
+ return this;
+ }
+
+ /**
+ * Assigns {@link RedirectStrategy} instance.
+ * <p/>
+ * Please note this value can be overridden by the {@link #disableRedirectHandling()}
+ * method.
+` */
+ public final HttpClientBuilder setRedirectStrategy(final RedirectStrategy redirectStrategy) {
+ this.redirectStrategy = redirectStrategy;
+ return this;
+ }
+
+ /**
+ * Disables automatic redirect handling.
+ */
+ public final HttpClientBuilder disableRedirectHandling() {
+ redirectHandlingDisabled = true;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ConnectionBackoffStrategy} instance.
+ */
+ public final HttpClientBuilder setConnectionBackoffStrategy(
+ final ConnectionBackoffStrategy connectionBackoffStrategy) {
+ this.connectionBackoffStrategy = connectionBackoffStrategy;
+ return this;
+ }
+
+ /**
+ * Assigns {@link BackoffManager} instance.
+ */
+ public final HttpClientBuilder setBackoffManager(final BackoffManager backoffManager) {
+ this.backoffManager = backoffManager;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ServiceUnavailableRetryStrategy} instance.
+ */
+ public final HttpClientBuilder setServiceUnavailableRetryStrategy(
+ final ServiceUnavailableRetryStrategy serviceUnavailStrategy) {
+ this.serviceUnavailStrategy = serviceUnavailStrategy;
+ return this;
+ }
+
+ /**
+ * Assigns default {@link CookieStore} instance which will be used for
+ * request execution if not explicitly set in the client execution context.
+ */
+ public final HttpClientBuilder setDefaultCookieStore(final CookieStore cookieStore) {
+ this.cookieStore = cookieStore;
+ return this;
+ }
+
+ /**
+ * Assigns default {@link CredentialsProvider} instance which will be used
+ * for request execution if not explicitly set in the client execution
+ * context.
+ */
+ public final HttpClientBuilder setDefaultCredentialsProvider(
+ final CredentialsProvider credentialsProvider) {
+ this.credentialsProvider = credentialsProvider;
+ return this;
+ }
+
+ /**
+ * Assigns default {@link ch.boye.httpclientandroidlib.auth.AuthScheme} registry which will
+ * be used for request execution if not explicitly set in the client execution
+ * context.
+ */
+ public final HttpClientBuilder setDefaultAuthSchemeRegistry(
+ final Lookup<AuthSchemeProvider> authSchemeRegistry) {
+ this.authSchemeRegistry = authSchemeRegistry;
+ return this;
+ }
+
+ /**
+ * Assigns default {@link ch.boye.httpclientandroidlib.cookie.CookieSpec} registry which will
+ * be used for request execution if not explicitly set in the client execution
+ * context.
+ */
+ public final HttpClientBuilder setDefaultCookieSpecRegistry(
+ final Lookup<CookieSpecProvider> cookieSpecRegistry) {
+ this.cookieSpecRegistry = cookieSpecRegistry;
+ return this;
+ }
+
+ /**
+ * Assigns default {@link RequestConfig} instance which will be used
+ * for request execution if not explicitly set in the client execution
+ * context.
+ */
+ public final HttpClientBuilder setDefaultRequestConfig(final RequestConfig config) {
+ this.defaultRequestConfig = config;
+ return this;
+ }
+
+ /**
+ * Use system properties when creating and configuring default
+ * implementations.
+ */
+ public final HttpClientBuilder useSystemProperties() {
+ systemProperties = true;
+ return this;
+ }
+
+ /**
+ * For internal use.
+ */
+ protected ClientExecChain decorateMainExec(final ClientExecChain mainExec) {
+ return mainExec;
+ }
+
+ /**
+ * For internal use.
+ */
+ protected ClientExecChain decorateProtocolExec(final ClientExecChain protocolExec) {
+ return protocolExec;
+ }
+
+ /**
+ * For internal use.
+ */
+ protected void addCloseable(final Closeable closeable) {
+ if (closeable == null) {
+ return;
+ }
+ if (closeables == null) {
+ closeables = new ArrayList<Closeable>();
+ }
+ closeables.add(closeable);
+ }
+
+ private static String[] split(final String s) {
+ if (TextUtils.isBlank(s)) {
+ return null;
+ }
+ return s.split(" *, *");
+ }
+
+ public CloseableHttpClient build() {
+ // Create main request executor
+ HttpRequestExecutor requestExec = this.requestExec;
+ if (requestExec == null) {
+ requestExec = new HttpRequestExecutor();
+ }
+ HttpClientConnectionManager connManager = this.connManager;
+ if (connManager == null) {
+ LayeredConnectionSocketFactory sslSocketFactory = this.sslSocketFactory;
+ if (sslSocketFactory == null) {
+ final String[] supportedProtocols = systemProperties ? split(
+ System.getProperty("https.protocols")) : null;
+ final String[] supportedCipherSuites = systemProperties ? split(
+ System.getProperty("https.cipherSuites")) : null;
+ X509HostnameVerifier hostnameVerifier = this.hostnameVerifier;
+ if (hostnameVerifier == null) {
+ hostnameVerifier = SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+ }
+ if (sslcontext != null) {
+ sslSocketFactory = new SSLConnectionSocketFactory(
+ sslcontext, supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ } else {
+ if (systemProperties) {
+ sslSocketFactory = new SSLConnectionSocketFactory(
+ (SSLSocketFactory) SSLSocketFactory.getDefault(),
+ supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ } else {
+ sslSocketFactory = new SSLConnectionSocketFactory(
+ SSLContexts.createDefault(),
+ hostnameVerifier);
+ }
+ }
+ }
+ @SuppressWarnings("resource")
+ final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(
+ RegistryBuilder.<ConnectionSocketFactory>create()
+ .register("http", PlainConnectionSocketFactory.getSocketFactory())
+ .register("https", sslSocketFactory)
+ .build());
+ if (defaultSocketConfig != null) {
+ poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
+ }
+ if (defaultConnectionConfig != null) {
+ poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);
+ }
+ if (systemProperties) {
+ String s = System.getProperty("http.keepAlive", "true");
+ if ("true".equalsIgnoreCase(s)) {
+ s = System.getProperty("http.maxConnections", "5");
+ final int max = Integer.parseInt(s);
+ poolingmgr.setDefaultMaxPerRoute(max);
+ poolingmgr.setMaxTotal(2 * max);
+ }
+ }
+ if (maxConnTotal > 0) {
+ poolingmgr.setMaxTotal(maxConnTotal);
+ }
+ if (maxConnPerRoute > 0) {
+ poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
+ }
+ connManager = poolingmgr;
+ }
+ ConnectionReuseStrategy reuseStrategy = this.reuseStrategy;
+ if (reuseStrategy == null) {
+ if (systemProperties) {
+ final String s = System.getProperty("http.keepAlive", "true");
+ if ("true".equalsIgnoreCase(s)) {
+ reuseStrategy = DefaultConnectionReuseStrategy.INSTANCE;
+ } else {
+ reuseStrategy = NoConnectionReuseStrategy.INSTANCE;
+ }
+ } else {
+ reuseStrategy = DefaultConnectionReuseStrategy.INSTANCE;
+ }
+ }
+ ConnectionKeepAliveStrategy keepAliveStrategy = this.keepAliveStrategy;
+ if (keepAliveStrategy == null) {
+ keepAliveStrategy = DefaultConnectionKeepAliveStrategy.INSTANCE;
+ }
+ AuthenticationStrategy targetAuthStrategy = this.targetAuthStrategy;
+ if (targetAuthStrategy == null) {
+ targetAuthStrategy = TargetAuthenticationStrategy.INSTANCE;
+ }
+ AuthenticationStrategy proxyAuthStrategy = this.proxyAuthStrategy;
+ if (proxyAuthStrategy == null) {
+ proxyAuthStrategy = ProxyAuthenticationStrategy.INSTANCE;
+ }
+ UserTokenHandler userTokenHandler = this.userTokenHandler;
+ if (userTokenHandler == null) {
+ if (!connectionStateDisabled) {
+ userTokenHandler = DefaultUserTokenHandler.INSTANCE;
+ } else {
+ userTokenHandler = NoopUserTokenHandler.INSTANCE;
+ }
+ }
+ ClientExecChain execChain = new MainClientExec(
+ requestExec,
+ connManager,
+ reuseStrategy,
+ keepAliveStrategy,
+ targetAuthStrategy,
+ proxyAuthStrategy,
+ userTokenHandler);
+
+ execChain = decorateMainExec(execChain);
+
+ HttpProcessor httpprocessor = this.httpprocessor;
+ if (httpprocessor == null) {
+
+ String userAgent = this.userAgent;
+ if (userAgent == null) {
+ if (systemProperties) {
+ userAgent = System.getProperty("http.agent");
+ }
+ if (userAgent == null) {
+ userAgent = DEFAULT_USER_AGENT;
+ }
+ }
+
+ final HttpProcessorBuilder b = HttpProcessorBuilder.create();
+ if (requestFirst != null) {
+ for (final HttpRequestInterceptor i: requestFirst) {
+ b.addFirst(i);
+ }
+ }
+ if (responseFirst != null) {
+ for (final HttpResponseInterceptor i: responseFirst) {
+ b.addFirst(i);
+ }
+ }
+ b.addAll(
+ new RequestDefaultHeaders(defaultHeaders),
+ new RequestContent(),
+ new RequestTargetHost(),
+ new RequestClientConnControl(),
+ new RequestUserAgent(userAgent),
+ new RequestExpectContinue());
+ if (!cookieManagementDisabled) {
+ b.add(new RequestAddCookies());
+ }
+ if (!contentCompressionDisabled) {
+ b.add(new RequestAcceptEncoding());
+ }
+ if (!authCachingDisabled) {
+ b.add(new RequestAuthCache());
+ }
+ if (!cookieManagementDisabled) {
+ b.add(new ResponseProcessCookies());
+ }
+ if (!contentCompressionDisabled) {
+ b.add(new ResponseContentEncoding());
+ }
+ if (requestLast != null) {
+ for (final HttpRequestInterceptor i: requestLast) {
+ b.addLast(i);
+ }
+ }
+ if (responseLast != null) {
+ for (final HttpResponseInterceptor i: responseLast) {
+ b.addLast(i);
+ }
+ }
+ httpprocessor = b.build();
+ }
+ execChain = new ProtocolExec(execChain, httpprocessor);
+
+ execChain = decorateProtocolExec(execChain);
+
+ // Add request retry executor, if not disabled
+ if (!automaticRetriesDisabled) {
+ HttpRequestRetryHandler retryHandler = this.retryHandler;
+ if (retryHandler == null) {
+ retryHandler = DefaultHttpRequestRetryHandler.INSTANCE;
+ }
+ execChain = new RetryExec(execChain, retryHandler);
+ }
+
+ HttpRoutePlanner routePlanner = this.routePlanner;
+ if (routePlanner == null) {
+ SchemePortResolver schemePortResolver = this.schemePortResolver;
+ if (schemePortResolver == null) {
+ schemePortResolver = DefaultSchemePortResolver.INSTANCE;
+ }
+ if (proxy != null) {
+ routePlanner = new DefaultProxyRoutePlanner(proxy, schemePortResolver);
+ } else if (systemProperties) {
+ routePlanner = new SystemDefaultRoutePlanner(
+ schemePortResolver, ProxySelector.getDefault());
+ } else {
+ routePlanner = new DefaultRoutePlanner(schemePortResolver);
+ }
+ }
+ // Add redirect executor, if not disabled
+ if (!redirectHandlingDisabled) {
+ RedirectStrategy redirectStrategy = this.redirectStrategy;
+ if (redirectStrategy == null) {
+ redirectStrategy = DefaultRedirectStrategy.INSTANCE;
+ }
+ execChain = new RedirectExec(execChain, routePlanner, redirectStrategy);
+ }
+
+ // Optionally, add service unavailable retry executor
+ final ServiceUnavailableRetryStrategy serviceUnavailStrategy = this.serviceUnavailStrategy;
+ if (serviceUnavailStrategy != null) {
+ execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategy);
+ }
+ // Optionally, add connection back-off executor
+ final BackoffManager backoffManager = this.backoffManager;
+ final ConnectionBackoffStrategy connectionBackoffStrategy = this.connectionBackoffStrategy;
+ if (backoffManager != null && connectionBackoffStrategy != null) {
+ execChain = new BackoffStrategyExec(execChain, connectionBackoffStrategy, backoffManager);
+ }
+
+ Lookup<AuthSchemeProvider> authSchemeRegistry = this.authSchemeRegistry;
+ if (authSchemeRegistry == null) {
+ authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
+ .register(AuthSchemes.BASIC, new BasicSchemeFactory())
+ .register(AuthSchemes.DIGEST, new DigestSchemeFactory())
+ .register(AuthSchemes.NTLM, new NTLMSchemeFactory())
+ /* SPNegoSchemeFactory removed by HttpClient for Android script. */
+ /* KerberosSchemeFactory removed by HttpClient for Android script. */
+ .build();
+ }
+ Lookup<CookieSpecProvider> cookieSpecRegistry = this.cookieSpecRegistry;
+ if (cookieSpecRegistry == null) {
+ cookieSpecRegistry = RegistryBuilder.<CookieSpecProvider>create()
+ .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
+ .register(CookieSpecs.STANDARD, new RFC2965SpecFactory())
+ .register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
+ .register(CookieSpecs.NETSCAPE, new NetscapeDraftSpecFactory())
+ .register(CookieSpecs.IGNORE_COOKIES, new IgnoreSpecFactory())
+ .register("rfc2109", new RFC2109SpecFactory())
+ .register("rfc2965", new RFC2965SpecFactory())
+ .build();
+ }
+
+ CookieStore defaultCookieStore = this.cookieStore;
+ if (defaultCookieStore == null) {
+ defaultCookieStore = new BasicCookieStore();
+ }
+
+ CredentialsProvider defaultCredentialsProvider = this.credentialsProvider;
+ if (defaultCredentialsProvider == null) {
+ if (systemProperties) {
+ defaultCredentialsProvider = new SystemDefaultCredentialsProvider();
+ } else {
+ defaultCredentialsProvider = new BasicCredentialsProvider();
+ }
+ }
+
+ return new InternalHttpClient(
+ execChain,
+ connManager,
+ routePlanner,
+ cookieSpecRegistry,
+ authSchemeRegistry,
+ defaultCookieStore,
+ defaultCredentialsProvider,
+ defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,
+ closeables != null ? new ArrayList<Closeable>(closeables) : null);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClients.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClients.java
new file mode 100644
index 000000000..294ac636b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpClients.java
@@ -0,0 +1,85 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.impl.conn.PoolingHttpClientConnectionManager;
+
+/**
+ * Factory methods for {@link CloseableHttpClient} instances.
+ * @since 4.3
+ */
+@Immutable
+public class HttpClients {
+
+ private HttpClients() {
+ super();
+ }
+
+ /**
+ * Creates builder object for construction of custom
+ * {@link CloseableHttpClient} instances.
+ */
+ public static HttpClientBuilder custom() {
+ return HttpClientBuilder.create();
+ }
+
+ /**
+ * Creates {@link CloseableHttpClient} instance with default
+ * configuration.
+ */
+ public static CloseableHttpClient createDefault() {
+ return HttpClientBuilder.create().build();
+ }
+
+ /**
+ * Creates {@link CloseableHttpClient} instance with default
+ * configuration based on ssytem properties.
+ */
+ public static CloseableHttpClient createSystem() {
+ return HttpClientBuilder.create().useSystemProperties().build();
+ }
+
+ /**
+ * Creates {@link CloseableHttpClient} instance that implements
+ * the most basic HTTP protocol support.
+ */
+ public static CloseableHttpClient createMinimal() {
+ return new MinimalHttpClient(new PoolingHttpClientConnectionManager());
+ }
+
+ /**
+ * Creates {@link CloseableHttpClient} instance that implements
+ * the most basic HTTP protocol support.
+ */
+ public static CloseableHttpClient createMinimal(final HttpClientConnectionManager connManager) {
+ return new MinimalHttpClient(connManager);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestFutureTask.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestFutureTask.java
new file mode 100644
index 000000000..b5f932403
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestFutureTask.java
@@ -0,0 +1,118 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.concurrent.FutureTask;
+
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+
+/**
+ * FutureTask implementation that wraps a HttpAsyncClientCallable and exposes various task
+ * specific metrics.
+ *
+ * @param <V>
+ */
+public class HttpRequestFutureTask<V> extends FutureTask<V> {
+
+ private final HttpUriRequest request;
+ private final HttpRequestTaskCallable<V> callable;
+
+ public HttpRequestFutureTask(
+ final HttpUriRequest request,
+ final HttpRequestTaskCallable<V> httpCallable) {
+ super(httpCallable);
+ this.request = request;
+ this.callable = httpCallable;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.util.concurrent.FutureTask#cancel(boolean)
+ */
+ @Override
+ public boolean cancel(final boolean mayInterruptIfRunning) {
+ callable.cancel();
+ if (mayInterruptIfRunning) {
+ request.abort();
+ }
+ return super.cancel(mayInterruptIfRunning);
+ }
+
+ /**
+ * @return the time in millis the task was scheduled.
+ */
+ public long scheduledTime() {
+ return callable.getScheduled();
+ }
+
+ /**
+ * @return the time in millis the task was started.
+ */
+ public long startedTime() {
+ return callable.getStarted();
+ }
+
+ /**
+ * @return the time in millis the task was finished/cancelled.
+ */
+ public long endedTime() {
+ if (isDone()) {
+ return callable.getEnded();
+ } else {
+ throw new IllegalStateException("Task is not done yet");
+ }
+ }
+
+ /**
+ * @return the time in millis it took to make the request (excluding the time it was
+ * scheduled to be executed).
+ */
+ public long requestDuration() {
+ if (isDone()) {
+ return endedTime() - startedTime();
+ } else {
+ throw new IllegalStateException("Task is not done yet");
+ }
+ }
+
+ /**
+ * @return the time in millis it took to execute the task from the moment it was scheduled.
+ */
+ public long taskDuration() {
+ if (isDone()) {
+ return endedTime() - scheduledTime();
+ } else {
+ throw new IllegalStateException("Task is not done yet");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return request.getRequestLine().getUri();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestTaskCallable.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestTaskCallable.java
new file mode 100644
index 000000000..42e95f0aa
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/HttpRequestTaskCallable.java
@@ -0,0 +1,119 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import ch.boye.httpclientandroidlib.client.HttpClient;
+import ch.boye.httpclientandroidlib.client.ResponseHandler;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.concurrent.FutureCallback;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+class HttpRequestTaskCallable<V> implements Callable<V> {
+
+ private final HttpUriRequest request;
+ private final HttpClient httpclient;
+ private final AtomicBoolean cancelled = new AtomicBoolean(false);
+
+ private final long scheduled = System.currentTimeMillis();
+ private long started = -1;
+ private long ended = -1;
+
+ private final HttpContext context;
+ private final ResponseHandler<V> responseHandler;
+ private final FutureCallback<V> callback;
+
+ private final FutureRequestExecutionMetrics metrics;
+
+ HttpRequestTaskCallable(
+ final HttpClient httpClient,
+ final HttpUriRequest request,
+ final HttpContext context,
+ final ResponseHandler<V> responseHandler,
+ final FutureCallback<V> callback,
+ final FutureRequestExecutionMetrics metrics) {
+ this.httpclient = httpClient;
+ this.responseHandler = responseHandler;
+ this.request = request;
+ this.context = context;
+ this.callback = callback;
+ this.metrics = metrics;
+ }
+
+ public long getScheduled() {
+ return scheduled;
+ }
+
+ public long getStarted() {
+ return started;
+ }
+
+ public long getEnded() {
+ return ended;
+ }
+
+ public V call() throws Exception {
+ if (!cancelled.get()) {
+ try {
+ metrics.getActiveConnections().incrementAndGet();
+ started = System.currentTimeMillis();
+ try {
+ metrics.getScheduledConnections().decrementAndGet();
+ final V result = httpclient.execute(request, responseHandler, context);
+ ended = System.currentTimeMillis();
+ metrics.getSuccessfulConnections().increment(started);
+ if (callback != null) {
+ callback.completed(result);
+ }
+ return result;
+ } catch (final Exception e) {
+ metrics.getFailedConnections().increment(started);
+ ended = System.currentTimeMillis();
+ if (callback != null) {
+ callback.failed(e);
+ }
+ throw e;
+ }
+ } finally {
+ metrics.getRequests().increment(started);
+ metrics.getTasks().increment(started);
+ metrics.getActiveConnections().decrementAndGet();
+ }
+ } else {
+ throw new IllegalStateException("call has been cancelled for request " + request.getURI());
+ }
+ }
+
+ public void cancel() {
+ cancelled.set(true);
+ if (callback != null) {
+ callback.cancelled();
+ }
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/InternalHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/InternalHttpClient.java
new file mode 100644
index 000000000..c445fe181
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/InternalHttpClient.java
@@ -0,0 +1,242 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeProvider;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.CookieStore;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.Configurable;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.params.ClientPNames;
+import ch.boye.httpclientandroidlib.client.params.HttpClientParamConfig;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.impl.execchain.ClientExecChain;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParamsNames;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Internal class.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+@SuppressWarnings("deprecation")
+class InternalHttpClient extends CloseableHttpClient {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final ClientExecChain execChain;
+ private final HttpClientConnectionManager connManager;
+ private final HttpRoutePlanner routePlanner;
+ private final Lookup<CookieSpecProvider> cookieSpecRegistry;
+ private final Lookup<AuthSchemeProvider> authSchemeRegistry;
+ private final CookieStore cookieStore;
+ private final CredentialsProvider credentialsProvider;
+ private final RequestConfig defaultConfig;
+ private final List<Closeable> closeables;
+
+ public InternalHttpClient(
+ final ClientExecChain execChain,
+ final HttpClientConnectionManager connManager,
+ final HttpRoutePlanner routePlanner,
+ final Lookup<CookieSpecProvider> cookieSpecRegistry,
+ final Lookup<AuthSchemeProvider> authSchemeRegistry,
+ final CookieStore cookieStore,
+ final CredentialsProvider credentialsProvider,
+ final RequestConfig defaultConfig,
+ final List<Closeable> closeables) {
+ super();
+ Args.notNull(execChain, "HTTP client exec chain");
+ Args.notNull(connManager, "HTTP connection manager");
+ Args.notNull(routePlanner, "HTTP route planner");
+ this.execChain = execChain;
+ this.connManager = connManager;
+ this.routePlanner = routePlanner;
+ this.cookieSpecRegistry = cookieSpecRegistry;
+ this.authSchemeRegistry = authSchemeRegistry;
+ this.cookieStore = cookieStore;
+ this.credentialsProvider = credentialsProvider;
+ this.defaultConfig = defaultConfig;
+ this.closeables = closeables;
+ }
+
+ private HttpRoute determineRoute(
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) throws HttpException {
+ HttpHost host = target;
+ if (host == null) {
+ host = (HttpHost) request.getParams().getParameter(ClientPNames.DEFAULT_HOST);
+ }
+ return this.routePlanner.determineRoute(host, request, context);
+ }
+
+ private void setupContext(final HttpClientContext context) {
+ if (context.getAttribute(HttpClientContext.TARGET_AUTH_STATE) == null) {
+ context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, new AuthState());
+ }
+ if (context.getAttribute(HttpClientContext.PROXY_AUTH_STATE) == null) {
+ context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, new AuthState());
+ }
+ if (context.getAttribute(HttpClientContext.AUTHSCHEME_REGISTRY) == null) {
+ context.setAttribute(HttpClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
+ }
+ if (context.getAttribute(HttpClientContext.COOKIESPEC_REGISTRY) == null) {
+ context.setAttribute(HttpClientContext.COOKIESPEC_REGISTRY, this.cookieSpecRegistry);
+ }
+ if (context.getAttribute(HttpClientContext.COOKIE_STORE) == null) {
+ context.setAttribute(HttpClientContext.COOKIE_STORE, this.cookieStore);
+ }
+ if (context.getAttribute(HttpClientContext.CREDS_PROVIDER) == null) {
+ context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider);
+ }
+ if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
+ context.setAttribute(HttpClientContext.REQUEST_CONFIG, this.defaultConfig);
+ }
+ }
+
+ @Override
+ protected CloseableHttpResponse doExecute(
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) throws IOException, ClientProtocolException {
+ Args.notNull(request, "HTTP request");
+ HttpExecutionAware execAware = null;
+ if (request instanceof HttpExecutionAware) {
+ execAware = (HttpExecutionAware) request;
+ }
+ try {
+ final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(request);
+ final HttpClientContext localcontext = HttpClientContext.adapt(
+ context != null ? context : new BasicHttpContext());
+ RequestConfig config = null;
+ if (request instanceof Configurable) {
+ config = ((Configurable) request).getConfig();
+ }
+ if (config == null) {
+ final HttpParams params = request.getParams();
+ if (params instanceof HttpParamsNames) {
+ if (!((HttpParamsNames) params).getNames().isEmpty()) {
+ config = HttpClientParamConfig.getRequestConfig(params);
+ }
+ } else {
+ config = HttpClientParamConfig.getRequestConfig(params);
+ }
+ }
+ if (config != null) {
+ localcontext.setRequestConfig(config);
+ }
+ setupContext(localcontext);
+ final HttpRoute route = determineRoute(target, wrapper, localcontext);
+ return this.execChain.execute(route, wrapper, localcontext, execAware);
+ } catch (final HttpException httpException) {
+ throw new ClientProtocolException(httpException);
+ }
+ }
+
+ public void close() {
+ this.connManager.shutdown();
+ if (this.closeables != null) {
+ for (final Closeable closeable: this.closeables) {
+ try {
+ closeable.close();
+ } catch (final IOException ex) {
+ this.log.error(ex.getMessage(), ex);
+ }
+ }
+ }
+ }
+
+ public HttpParams getParams() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ClientConnectionManager getConnectionManager() {
+
+ return new ClientConnectionManager() {
+
+ public void shutdown() {
+ connManager.shutdown();
+ }
+
+ public ClientConnectionRequest requestConnection(
+ final HttpRoute route, final Object state) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void releaseConnection(
+ final ManagedClientConnection conn,
+ final long validDuration, final TimeUnit timeUnit) {
+ throw new UnsupportedOperationException();
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
+ connManager.closeIdleConnections(idletime, tunit);
+ }
+
+ public void closeExpiredConnections() {
+ connManager.closeExpiredConnections();
+ }
+
+ };
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/LaxRedirectStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/LaxRedirectStrategy.java
new file mode 100644
index 000000000..47688e642
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/LaxRedirectStrategy.java
@@ -0,0 +1,65 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.methods.HttpGet;
+import ch.boye.httpclientandroidlib.client.methods.HttpHead;
+import ch.boye.httpclientandroidlib.client.methods.HttpPost;
+
+/**
+ * Lax {@link ch.boye.httpclientandroidlib.client.RedirectStrategy} implementation
+ * that automatically redirects all HEAD, GET and POST requests.
+ * This strategy relaxes restrictions on automatic redirection of
+ * POST methods imposed by the HTTP specification.
+ *
+ * @since 4.2
+ */
+@Immutable
+public class LaxRedirectStrategy extends DefaultRedirectStrategy {
+
+ /**
+ * Redirectable methods.
+ */
+ private static final String[] REDIRECT_METHODS = new String[] {
+ HttpGet.METHOD_NAME,
+ HttpPost.METHOD_NAME,
+ HttpHead.METHOD_NAME
+ };
+
+ @Override
+ protected boolean isRedirectable(final String method) {
+ for (final String m: REDIRECT_METHODS) {
+ if (m.equalsIgnoreCase(method)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/MinimalHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/MinimalHttpClient.java
new file mode 100644
index 000000000..8b0c21127
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/MinimalHttpClient.java
@@ -0,0 +1,156 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.Configurable;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.execchain.MinimalClientExec;
+import ch.boye.httpclientandroidlib.params.BasicHttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Internal class.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+@SuppressWarnings("deprecation")
+class MinimalHttpClient extends CloseableHttpClient {
+
+ private final HttpClientConnectionManager connManager;
+ private final MinimalClientExec requestExecutor;
+ private final HttpParams params;
+
+ public MinimalHttpClient(
+ final HttpClientConnectionManager connManager) {
+ super();
+ this.connManager = Args.notNull(connManager, "HTTP connection manager");
+ this.requestExecutor = new MinimalClientExec(
+ new HttpRequestExecutor(),
+ connManager,
+ DefaultConnectionReuseStrategy.INSTANCE,
+ DefaultConnectionKeepAliveStrategy.INSTANCE);
+ this.params = new BasicHttpParams();
+ }
+
+ @Override
+ protected CloseableHttpResponse doExecute(
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) throws IOException, ClientProtocolException {
+ Args.notNull(target, "Target host");
+ Args.notNull(request, "HTTP request");
+ HttpExecutionAware execAware = null;
+ if (request instanceof HttpExecutionAware) {
+ execAware = (HttpExecutionAware) request;
+ }
+ try {
+ final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(request);
+ final HttpClientContext localcontext = HttpClientContext.adapt(
+ context != null ? context : new BasicHttpContext());
+ final HttpRoute route = new HttpRoute(target);
+ RequestConfig config = null;
+ if (request instanceof Configurable) {
+ config = ((Configurable) request).getConfig();
+ }
+ if (config != null) {
+ localcontext.setRequestConfig(config);
+ }
+ return this.requestExecutor.execute(route, wrapper, localcontext, execAware);
+ } catch (final HttpException httpException) {
+ throw new ClientProtocolException(httpException);
+ }
+ }
+
+ public HttpParams getParams() {
+ return this.params;
+ }
+
+ public void close() {
+ this.connManager.shutdown();
+ }
+
+ public ClientConnectionManager getConnectionManager() {
+
+ return new ClientConnectionManager() {
+
+ public void shutdown() {
+ connManager.shutdown();
+ }
+
+ public ClientConnectionRequest requestConnection(
+ final HttpRoute route, final Object state) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void releaseConnection(
+ final ManagedClientConnection conn,
+ final long validDuration, final TimeUnit timeUnit) {
+ throw new UnsupportedOperationException();
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
+ connManager.closeIdleConnections(idletime, tunit);
+ }
+
+ public void closeExpiredConnections() {
+ connManager.closeExpiredConnections();
+ }
+
+ };
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NoopUserTokenHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NoopUserTokenHandler.java
new file mode 100644
index 000000000..1e8eb3bde
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NoopUserTokenHandler.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.UserTokenHandler;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Noop implementation of {@link UserTokenHandler} that always returns <code>null</code>.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class NoopUserTokenHandler implements UserTokenHandler {
+
+ public static final NoopUserTokenHandler INSTANCE = new NoopUserTokenHandler();
+
+ public Object getUserToken(final HttpContext context) {
+ return null;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NullBackoffStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NullBackoffStrategy.java
new file mode 100644
index 000000000..8cad78d75
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/NullBackoffStrategy.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.client.ConnectionBackoffStrategy;
+
+/**
+ * This is a {@link ConnectionBackoffStrategy} that never backs off,
+ * for compatibility with existing behavior.
+ *
+ * @since 4.2
+ */
+public class NullBackoffStrategy implements ConnectionBackoffStrategy {
+
+ public boolean shouldBackoff(final Throwable t) {
+ return false;
+ }
+
+ public boolean shouldBackoff(final HttpResponse resp) {
+ return false;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyAuthenticationStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyAuthenticationStrategy.java
new file mode 100644
index 000000000..636143630
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyAuthenticationStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+
+/**
+ * Default {@link ch.boye.httpclientandroidlib.client.AuthenticationStrategy} implementation
+ * for proxy host authentication.
+ *
+ * @since 4.2
+ */
+@Immutable
+public class ProxyAuthenticationStrategy extends AuthenticationStrategyImpl {
+
+ public static final ProxyAuthenticationStrategy INSTANCE = new ProxyAuthenticationStrategy();
+
+ public ProxyAuthenticationStrategy() {
+ super(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED, AUTH.PROXY_AUTH);
+ }
+
+ @Override
+ Collection<String> getPreferredAuthSchemes(final RequestConfig config) {
+ return config.getProxyPreferredAuthSchemes();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyClient.java
new file mode 100644
index 000000000..e1211bc4b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/ProxyClient.java
@@ -0,0 +1,254 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthSchemeRegistry;
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.client.config.AuthSchemes;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.params.HttpClientParamConfig;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.client.protocol.RequestClientConnControl;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.conn.HttpConnectionFactory;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.RouteInfo.LayerType;
+import ch.boye.httpclientandroidlib.conn.routing.RouteInfo.TunnelType;
+import ch.boye.httpclientandroidlib.entity.BufferedHttpEntity;
+import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.auth.BasicSchemeFactory;
+import ch.boye.httpclientandroidlib.impl.auth.DigestSchemeFactory;
+import ch.boye.httpclientandroidlib.impl.auth.HttpAuthenticator;
+/* KerberosSchemeFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.impl.auth.NTLMSchemeFactory;
+/* SPNegoSchemeFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.impl.conn.ManagedHttpClientConnectionFactory;
+import ch.boye.httpclientandroidlib.impl.execchain.TunnelRefusedException;
+import ch.boye.httpclientandroidlib.message.BasicHttpRequest;
+import ch.boye.httpclientandroidlib.params.BasicHttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParamConfig;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.protocol.HttpCoreContext;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor;
+import ch.boye.httpclientandroidlib.protocol.ImmutableHttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.RequestTargetHost;
+import ch.boye.httpclientandroidlib.protocol.RequestUserAgent;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * ProxyClient can be used to establish a tunnel via an HTTP proxy.
+ */
+@SuppressWarnings("deprecation")
+public class ProxyClient {
+
+ private final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory;
+ private final ConnectionConfig connectionConfig;
+ private final RequestConfig requestConfig;
+ private final HttpProcessor httpProcessor;
+ private final HttpRequestExecutor requestExec;
+ private final ProxyAuthenticationStrategy proxyAuthStrategy;
+ private final HttpAuthenticator authenticator;
+ private final AuthState proxyAuthState;
+ private final AuthSchemeRegistry authSchemeRegistry;
+ private final ConnectionReuseStrategy reuseStrategy;
+
+ /**
+ * @since 4.3
+ */
+ public ProxyClient(
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,
+ final ConnectionConfig connectionConfig,
+ final RequestConfig requestConfig) {
+ super();
+ this.connFactory = connFactory != null ? connFactory : ManagedHttpClientConnectionFactory.INSTANCE;
+ this.connectionConfig = connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
+ this.requestConfig = requestConfig != null ? requestConfig : RequestConfig.DEFAULT;
+ this.httpProcessor = new ImmutableHttpProcessor(
+ new RequestTargetHost(), new RequestClientConnControl(), new RequestUserAgent());
+ this.requestExec = new HttpRequestExecutor();
+ this.proxyAuthStrategy = new ProxyAuthenticationStrategy();
+ this.authenticator = new HttpAuthenticator();
+ this.proxyAuthState = new AuthState();
+ this.authSchemeRegistry = new AuthSchemeRegistry();
+ this.authSchemeRegistry.register(AuthSchemes.BASIC, new BasicSchemeFactory());
+ this.authSchemeRegistry.register(AuthSchemes.DIGEST, new DigestSchemeFactory());
+ this.authSchemeRegistry.register(AuthSchemes.NTLM, new NTLMSchemeFactory());
+ /* SPNegoSchemeFactory removed by HttpClient for Android script. */
+ /* KerberosSchemeFactory removed by HttpClient for Android script. */
+ this.reuseStrategy = new DefaultConnectionReuseStrategy();
+ }
+
+ /**
+ * @deprecated (4.3) use {@link ProxyClient#ProxyClient(HttpConnectionFactory, ConnectionConfig, RequestConfig)}
+ */
+ @Deprecated
+ public ProxyClient(final HttpParams params) {
+ this(null,
+ HttpParamConfig.getConnectionConfig(params),
+ HttpClientParamConfig.getRequestConfig(params));
+ }
+
+ /**
+ * @since 4.3
+ */
+ public ProxyClient(final RequestConfig requestConfig) {
+ this(null, null, requestConfig);
+ }
+
+ public ProxyClient() {
+ this(null, null, null);
+ }
+
+ /**
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public HttpParams getParams() {
+ return new BasicHttpParams();
+ }
+
+ /**
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public AuthSchemeRegistry getAuthSchemeRegistry() {
+ return this.authSchemeRegistry;
+ }
+
+ public Socket tunnel(
+ final HttpHost proxy,
+ final HttpHost target,
+ final Credentials credentials) throws IOException, HttpException {
+ Args.notNull(proxy, "Proxy host");
+ Args.notNull(target, "Target host");
+ Args.notNull(credentials, "Credentials");
+ HttpHost host = target;
+ if (host.getPort() <= 0) {
+ host = new HttpHost(host.getHostName(), 80, host.getSchemeName());
+ }
+ final HttpRoute route = new HttpRoute(
+ host,
+ this.requestConfig.getLocalAddress(),
+ proxy, false, TunnelType.TUNNELLED, LayerType.PLAIN);
+
+ final ManagedHttpClientConnection conn = this.connFactory.create(
+ route, this.connectionConfig);
+ final HttpContext context = new BasicHttpContext();
+ HttpResponse response;
+
+ final HttpRequest connect = new BasicHttpRequest(
+ "CONNECT", host.toHostString(), HttpVersion.HTTP_1_1);
+
+ final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
+ credsProvider.setCredentials(new AuthScope(proxy), credentials);
+
+ // Populate the execution context
+ context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
+ context.setAttribute(HttpCoreContext.HTTP_CONNECTION, conn);
+ context.setAttribute(HttpCoreContext.HTTP_REQUEST, connect);
+ context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
+ context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, this.proxyAuthState);
+ context.setAttribute(HttpClientContext.CREDS_PROVIDER, credsProvider);
+ context.setAttribute(HttpClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
+ context.setAttribute(HttpClientContext.REQUEST_CONFIG, this.requestConfig);
+
+ this.requestExec.preProcess(connect, this.httpProcessor, context);
+
+ for (;;) {
+ if (!conn.isOpen()) {
+ final Socket socket = new Socket(proxy.getHostName(), proxy.getPort());
+ conn.bind(socket);
+ }
+
+ this.authenticator.generateAuthResponse(connect, this.proxyAuthState, context);
+
+ response = this.requestExec.execute(connect, conn, context);
+
+ final int status = response.getStatusLine().getStatusCode();
+ if (status < 200) {
+ throw new HttpException("Unexpected response to CONNECT request: " +
+ response.getStatusLine());
+ }
+ if (this.authenticator.isAuthenticationRequested(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ if (this.authenticator.handleAuthChallenge(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ // Retry request
+ if (this.reuseStrategy.keepAlive(response, context)) {
+ // Consume response content
+ final HttpEntity entity = response.getEntity();
+ EntityUtils.consume(entity);
+ } else {
+ conn.close();
+ }
+ // discard previous auth header
+ connect.removeHeaders(AUTH.PROXY_AUTH_RESP);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ final int status = response.getStatusLine().getStatusCode();
+
+ if (status > 299) {
+
+ // Buffer response content
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ response.setEntity(new BufferedHttpEntity(entity));
+ }
+
+ conn.close();
+ throw new TunnelRefusedException("CONNECT refused by proxy: " +
+ response.getStatusLine(), response);
+ }
+ return conn.getSocket();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RedirectLocations.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RedirectLocations.java
new file mode 100644
index 000000000..872dc167f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RedirectLocations.java
@@ -0,0 +1,227 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.URI;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * This class represents a collection of {@link java.net.URI}s used
+ * as redirect locations.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // HashSet/ArrayList are not synch.
+public class RedirectLocations extends AbstractList<Object> {
+
+ private final Set<URI> unique;
+ private final List<URI> all;
+
+ public RedirectLocations() {
+ super();
+ this.unique = new HashSet<URI>();
+ this.all = new ArrayList<URI>();
+ }
+
+ /**
+ * Test if the URI is present in the collection.
+ */
+ public boolean contains(final URI uri) {
+ return this.unique.contains(uri);
+ }
+
+ /**
+ * Adds a new URI to the collection.
+ */
+ public void add(final URI uri) {
+ this.unique.add(uri);
+ this.all.add(uri);
+ }
+
+ /**
+ * Removes a URI from the collection.
+ */
+ public boolean remove(final URI uri) {
+ final boolean removed = this.unique.remove(uri);
+ if (removed) {
+ final Iterator<URI> it = this.all.iterator();
+ while (it.hasNext()) {
+ final URI current = it.next();
+ if (current.equals(uri)) {
+ it.remove();
+ }
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * Returns all redirect {@link URI}s in the order they were added to the collection.
+ *
+ * @return list of all URIs
+ *
+ * @since 4.1
+ */
+ public List<URI> getAll() {
+ return new ArrayList<URI>(this.all);
+ }
+
+ /**
+ * Returns the URI at the specified position in this list.
+ *
+ * @param index
+ * index of the location to return
+ * @return the URI at the specified position in this list
+ * @throws IndexOutOfBoundsException
+ * if the index is out of range (
+ * <tt>index &lt; 0 || index &gt;= size()</tt>)
+ * @since 4.3
+ */
+ @Override
+ public URI get(final int index) {
+ return this.all.get(index);
+ }
+
+ /**
+ * Returns the number of elements in this list. If this list contains more
+ * than <tt>Integer.MAX_VALUE</tt> elements, returns
+ * <tt>Integer.MAX_VALUE</tt>.
+ *
+ * @return the number of elements in this list
+ * @since 4.3
+ */
+ @Override
+ public int size() {
+ return this.all.size();
+ }
+
+ /**
+ * Replaces the URI at the specified position in this list with the
+ * specified element (must be a URI).
+ *
+ * @param index
+ * index of the element to replace
+ * @param element
+ * URI to be stored at the specified position
+ * @return the URI previously at the specified position
+ * @throws UnsupportedOperationException
+ * if the <tt>set</tt> operation is not supported by this list
+ * @throws ClassCastException
+ * if the element is not a {@link URI}
+ * @throws NullPointerException
+ * if the specified element is null and this list does not
+ * permit null elements
+ * @throws IndexOutOfBoundsException
+ * if the index is out of range (
+ * <tt>index &lt; 0 || index &gt;= size()</tt>)
+ * @since 4.3
+ */
+ @Override
+ public Object set(final int index, final Object element) {
+ final URI removed = this.all.set(index, (URI) element);
+ this.unique.remove(removed);
+ this.unique.add((URI) element);
+ if (this.all.size() != this.unique.size()) {
+ this.unique.addAll(this.all);
+ }
+ return removed;
+ }
+
+ /**
+ * Inserts the specified element at the specified position in this list
+ * (must be a URI). Shifts the URI currently at that position (if any) and
+ * any subsequent URIs to the right (adds one to their indices).
+ *
+ * @param index
+ * index at which the specified element is to be inserted
+ * @param element
+ * URI to be inserted
+ * @throws UnsupportedOperationException
+ * if the <tt>add</tt> operation is not supported by this list
+ * @throws ClassCastException
+ * if the element is not a {@link URI}
+ * @throws NullPointerException
+ * if the specified element is null and this list does not
+ * permit null elements
+ * @throws IndexOutOfBoundsException
+ * if the index is out of range (
+ * <tt>index &lt; 0 || index &gt; size()</tt>)
+ * @since 4.3
+ */
+ @Override
+ public void add(final int index, final Object element) {
+ this.all.add(index, (URI) element);
+ this.unique.add((URI) element);
+ }
+
+ /**
+ * Removes the URI at the specified position in this list. Shifts any
+ * subsequent URIs to the left (subtracts one from their indices). Returns
+ * the URI that was removed from the list.
+ *
+ * @param index
+ * the index of the URI to be removed
+ * @return the URI previously at the specified position
+ * @throws IndexOutOfBoundsException
+ * if the index is out of range (
+ * <tt>index &lt; 0 || index &gt;= size()</tt>)
+ * @since 4.3
+ */
+ @Override
+ public URI remove(final int index) {
+ final URI removed = this.all.remove(index);
+ this.unique.remove(removed);
+ if (this.all.size() != this.unique.size()) {
+ this.unique.addAll(this.all);
+ }
+ return removed;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this collection contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this collection
+ * contains at least one element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+ *
+ * @param o element whose presence in this collection is to be tested
+ * @return <tt>true</tt> if this collection contains the specified
+ * element
+ */
+ @Override
+ public boolean contains(final Object o) {
+ return this.unique.contains(o);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RequestWrapper.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RequestWrapper.java
new file mode 100644
index 000000000..3577b61a6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RequestWrapper.java
@@ -0,0 +1,164 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.message.AbstractHttpMessage;
+import ch.boye.httpclientandroidlib.message.BasicRequestLine;
+import ch.boye.httpclientandroidlib.params.HttpProtocolParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A wrapper class for {@link HttpRequest}s that can be used to change
+ * properties of the current request without modifying the original
+ * object.
+ * </p>
+ * This class is also capable of resetting the request headers to
+ * the state of the original request.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) do not use.
+ */
+@NotThreadSafe
+@Deprecated
+public class RequestWrapper extends AbstractHttpMessage implements HttpUriRequest {
+
+ private final HttpRequest original;
+
+ private URI uri;
+ private String method;
+ private ProtocolVersion version;
+ private int execCount;
+
+ public RequestWrapper(final HttpRequest request) throws ProtocolException {
+ super();
+ Args.notNull(request, "HTTP request");
+ this.original = request;
+ setParams(request.getParams());
+ setHeaders(request.getAllHeaders());
+ // Make a copy of the original URI
+ if (request instanceof HttpUriRequest) {
+ this.uri = ((HttpUriRequest) request).getURI();
+ this.method = ((HttpUriRequest) request).getMethod();
+ this.version = null;
+ } else {
+ final RequestLine requestLine = request.getRequestLine();
+ try {
+ this.uri = new URI(requestLine.getUri());
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException("Invalid request URI: "
+ + requestLine.getUri(), ex);
+ }
+ this.method = requestLine.getMethod();
+ this.version = request.getProtocolVersion();
+ }
+ this.execCount = 0;
+ }
+
+ public void resetHeaders() {
+ // Make a copy of original headers
+ this.headergroup.clear();
+ setHeaders(this.original.getAllHeaders());
+ }
+
+ public String getMethod() {
+ return this.method;
+ }
+
+ public void setMethod(final String method) {
+ Args.notNull(method, "Method name");
+ this.method = method;
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ if (this.version == null) {
+ this.version = HttpProtocolParams.getVersion(getParams());
+ }
+ return this.version;
+ }
+
+ public void setProtocolVersion(final ProtocolVersion version) {
+ this.version = version;
+ }
+
+
+ public URI getURI() {
+ return this.uri;
+ }
+
+ public void setURI(final URI uri) {
+ this.uri = uri;
+ }
+
+ public RequestLine getRequestLine() {
+ final String method = getMethod();
+ final ProtocolVersion ver = getProtocolVersion();
+ String uritext = null;
+ if (uri != null) {
+ uritext = uri.toASCIIString();
+ }
+ if (uritext == null || uritext.length() == 0) {
+ uritext = "/";
+ }
+ return new BasicRequestLine(method, uritext, ver);
+ }
+
+ public void abort() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isAborted() {
+ return false;
+ }
+
+ public HttpRequest getOriginal() {
+ return this.original;
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public int getExecCount() {
+ return this.execCount;
+ }
+
+ public void incrementExecCount() {
+ this.execCount++;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RoutedRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RoutedRequest.java
new file mode 100644
index 000000000..2e5ff76e9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/RoutedRequest.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+
+/**
+ * A request with the route along which it should be sent.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) do not use.
+ */
+@Deprecated
+@NotThreadSafe // RequestWrapper is @NotThreadSafe
+public class RoutedRequest {
+
+ protected final RequestWrapper request; // @NotThreadSafe
+ protected final HttpRoute route; // @Immutable
+
+ /**
+ * Creates a new routed request.
+ *
+ * @param req the request
+ * @param route the route
+ */
+ public RoutedRequest(final RequestWrapper req, final HttpRoute route) {
+ super();
+ this.request = req;
+ this.route = route;
+ }
+
+ public final RequestWrapper getRequest() {
+ return request;
+ }
+
+ public final HttpRoute getRoute() {
+ return route;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/StandardHttpRequestRetryHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/StandardHttpRequestRetryHandler.java
new file mode 100644
index 000000000..ec0ce7e00
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/StandardHttpRequestRetryHandler.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * {@link ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler} which assumes
+ * that all requested HTTP methods which should be idempotent according
+ * to RFC-2616 are in fact idempotent and can be retried.
+ * <p/>
+ * According to RFC-2616 section 9.1.2 the idempotent HTTP methods are:
+ * GET, HEAD, PUT, DELETE, OPTIONS, and TRACE
+ *
+ * @since 4.2
+ */
+@Immutable
+public class StandardHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {
+
+ private final Map<String, Boolean> idempotentMethods;
+
+ /**
+ * Default constructor
+ */
+ public StandardHttpRequestRetryHandler(final int retryCount, final boolean requestSentRetryEnabled) {
+ super(retryCount, requestSentRetryEnabled);
+ this.idempotentMethods = new ConcurrentHashMap<String, Boolean>();
+ this.idempotentMethods.put("GET", Boolean.TRUE);
+ this.idempotentMethods.put("HEAD", Boolean.TRUE);
+ this.idempotentMethods.put("PUT", Boolean.TRUE);
+ this.idempotentMethods.put("DELETE", Boolean.TRUE);
+ this.idempotentMethods.put("OPTIONS", Boolean.TRUE);
+ this.idempotentMethods.put("TRACE", Boolean.TRUE);
+ }
+
+ /**
+ * Default constructor
+ */
+ public StandardHttpRequestRetryHandler() {
+ this(3, false);
+ }
+
+ @Override
+ protected boolean handleAsIdempotent(final HttpRequest request) {
+ final String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
+ final Boolean b = this.idempotentMethods.get(method);
+ return b != null && b.booleanValue();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemClock.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemClock.java
new file mode 100644
index 000000000..b037af841
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemClock.java
@@ -0,0 +1,40 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+/**
+ * The actual system clock.
+ *
+ * @since 4.2
+ */
+class SystemClock implements Clock {
+
+ public long getCurrentTime() {
+ return System.currentTimeMillis();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultCredentialsProvider.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultCredentialsProvider.java
new file mode 100644
index 000000000..1327b71dc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultCredentialsProvider.java
@@ -0,0 +1,145 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.Credentials;
+import ch.boye.httpclientandroidlib.auth.NTCredentials;
+import ch.boye.httpclientandroidlib.auth.UsernamePasswordCredentials;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.config.AuthSchemes;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Implementation of {@link CredentialsProvider} backed by standard
+ * JRE {@link Authenticator}.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public class SystemDefaultCredentialsProvider implements CredentialsProvider {
+
+ private static final Map<String, String> SCHEME_MAP;
+
+ static {
+ SCHEME_MAP = new ConcurrentHashMap<String, String>();
+ SCHEME_MAP.put(AuthSchemes.BASIC.toUpperCase(Locale.ENGLISH), "Basic");
+ SCHEME_MAP.put(AuthSchemes.DIGEST.toUpperCase(Locale.ENGLISH), "Digest");
+ SCHEME_MAP.put(AuthSchemes.NTLM.toUpperCase(Locale.ENGLISH), "NTLM");
+ SCHEME_MAP.put(AuthSchemes.SPNEGO.toUpperCase(Locale.ENGLISH), "SPNEGO");
+ SCHEME_MAP.put(AuthSchemes.KERBEROS.toUpperCase(Locale.ENGLISH), "Kerberos");
+ }
+
+ private static String translateScheme(final String key) {
+ if (key == null) {
+ return null;
+ }
+ final String s = SCHEME_MAP.get(key);
+ return s != null ? s : key;
+ }
+
+ private final BasicCredentialsProvider internal;
+
+ /**
+ * Default constructor.
+ */
+ public SystemDefaultCredentialsProvider() {
+ super();
+ this.internal = new BasicCredentialsProvider();
+ }
+
+ public void setCredentials(final AuthScope authscope, final Credentials credentials) {
+ internal.setCredentials(authscope, credentials);
+ }
+
+ private static PasswordAuthentication getSystemCreds(
+ final AuthScope authscope,
+ final Authenticator.RequestorType requestorType) {
+ final String hostname = authscope.getHost();
+ final int port = authscope.getPort();
+ final String protocol = port == 443 ? "https" : "http";
+ return Authenticator.requestPasswordAuthentication(
+ hostname,
+ null,
+ port,
+ protocol,
+ null,
+ translateScheme(authscope.getScheme()),
+ null,
+ requestorType);
+ }
+
+ public Credentials getCredentials(final AuthScope authscope) {
+ Args.notNull(authscope, "Auth scope");
+ final Credentials localcreds = internal.getCredentials(authscope);
+ if (localcreds != null) {
+ return localcreds;
+ }
+ if (authscope.getHost() != null) {
+ PasswordAuthentication systemcreds = getSystemCreds(
+ authscope, Authenticator.RequestorType.SERVER);
+ if (systemcreds == null) {
+ systemcreds = getSystemCreds(
+ authscope, Authenticator.RequestorType.PROXY);
+ }
+ if (systemcreds != null) {
+ final String domain = System.getProperty("http.auth.ntlm.domain");
+ if (domain != null) {
+ return new NTCredentials(
+ systemcreds.getUserName(),
+ new String(systemcreds.getPassword()),
+ null, domain);
+ } else {
+ if (AuthSchemes.NTLM.equalsIgnoreCase(authscope.getScheme())) {
+ // Domian may be specified in a fully qualified user name
+ return new NTCredentials(
+ systemcreds.getUserName(),
+ new String(systemcreds.getPassword()),
+ null, null);
+ } else {
+ return new UsernamePasswordCredentials(
+ systemcreds.getUserName(),
+ new String(systemcreds.getPassword()));
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public void clear() {
+ internal.clear();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultHttpClient.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultHttpClient.java
new file mode 100644
index 000000000..0806537ed
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/SystemDefaultHttpClient.java
@@ -0,0 +1,149 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.net.ProxySelector;
+
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.NoConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.conn.PoolingClientConnectionManager;
+import ch.boye.httpclientandroidlib.impl.conn.ProxySelectorRoutePlanner;
+import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * An extension of {@link DefaultHttpClient} pre-configured using system properties.
+ * <p>
+ * The following system properties are taken into account by this class:
+ * <ul>
+ * <li>ssl.TrustManagerFactory.algorithm</li>
+ * <li>javax.net.ssl.trustStoreType</li>
+ * <li>javax.net.ssl.trustStore</li>
+ * <li>javax.net.ssl.trustStoreProvider</li>
+ * <li>javax.net.ssl.trustStorePassword</li>
+ * <li>java.home</li>
+ * <li>ssl.KeyManagerFactory.algorithm</li>
+ * <li>javax.net.ssl.keyStoreType</li>
+ * <li>javax.net.ssl.keyStore</li>
+ * <li>javax.net.ssl.keyStoreProvider</li>
+ * <li>javax.net.ssl.keyStorePassword</li>
+ * <li>http.proxyHost</li>
+ * <li>http.proxyPort</li>
+ * <li>http.nonProxyHosts</li>
+ * <li>http.keepAlive</li>
+ * <li>http.maxConnections</li>
+ * </ul>
+ * <p>
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#PROTOCOL_VERSION}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#USE_EXPECT_CONTINUE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#WAIT_FOR_CONTINUE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#USER_AGENT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#TCP_NODELAY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_LINGER}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_REUSEADDR}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#STALE_CONNECTION_CHECK}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#FORCED_ROUTE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#LOCAL_ADDRESS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#DEFAULT_PROXY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#DATE_PATTERNS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames#SINGLE_COOKIE_HEADER}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.auth.params.AuthPNames#CREDENTIAL_CHARSET}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#COOKIE_POLICY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#HANDLE_AUTHENTICATION}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#HANDLE_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#MAX_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#ALLOW_CIRCULAR_REDIRECTS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#VIRTUAL_HOST}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#DEFAULT_HOST}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#DEFAULT_HEADERS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.client.params.ClientPNames#CONN_MANAGER_TIMEOUT}</li>
+ * </ul>
+ * </p>
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link HttpClientBuilder}
+ */
+@ThreadSafe
+@Deprecated
+public class SystemDefaultHttpClient extends DefaultHttpClient {
+
+ public SystemDefaultHttpClient(final HttpParams params) {
+ super(null, params);
+ }
+
+ public SystemDefaultHttpClient() {
+ super(null, null);
+ }
+
+ @Override
+ protected ClientConnectionManager createClientConnectionManager() {
+ final PoolingClientConnectionManager connmgr = new PoolingClientConnectionManager(
+ SchemeRegistryFactory.createSystemDefault());
+ String s = System.getProperty("http.keepAlive", "true");
+ if ("true".equalsIgnoreCase(s)) {
+ s = System.getProperty("http.maxConnections", "5");
+ final int max = Integer.parseInt(s);
+ connmgr.setDefaultMaxPerRoute(max);
+ connmgr.setMaxTotal(2 * max);
+ }
+ return connmgr;
+ }
+
+ @Override
+ protected HttpRoutePlanner createHttpRoutePlanner() {
+ return new ProxySelectorRoutePlanner(getConnectionManager().getSchemeRegistry(),
+ ProxySelector.getDefault());
+ }
+
+ @Override
+ protected ConnectionReuseStrategy createConnectionReuseStrategy() {
+ final String s = System.getProperty("http.keepAlive", "true");
+ if ("true".equalsIgnoreCase(s)) {
+ return new DefaultConnectionReuseStrategy();
+ } else {
+ return new NoConnectionReuseStrategy();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TargetAuthenticationStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TargetAuthenticationStrategy.java
new file mode 100644
index 000000000..486167dc1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TargetAuthenticationStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+
+/**
+ * Default {@link ch.boye.httpclientandroidlib.client.AuthenticationStrategy} implementation
+ * for proxy host authentication.
+ *
+ * @since 4.2
+ */
+@Immutable
+public class TargetAuthenticationStrategy extends AuthenticationStrategyImpl {
+
+ public static final TargetAuthenticationStrategy INSTANCE = new TargetAuthenticationStrategy();
+
+ public TargetAuthenticationStrategy() {
+ super(HttpStatus.SC_UNAUTHORIZED, AUTH.WWW_AUTH);
+ }
+
+ @Override
+ Collection<String> getPreferredAuthSchemes(final RequestConfig config) {
+ return config.getTargetPreferredAuthSchemes();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TunnelRefusedException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TunnelRefusedException.java
new file mode 100644
index 000000000..97edac1f0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/TunnelRefusedException.java
@@ -0,0 +1,58 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals that the tunnel request was rejected by the proxy host.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) reserved for internal use.
+ */
+@Deprecated
+@Immutable
+public class TunnelRefusedException extends HttpException {
+
+ private static final long serialVersionUID = -8646722842745617323L;
+
+ private final HttpResponse response;
+
+ public TunnelRefusedException(final String message, final HttpResponse response) {
+ super(message);
+ this.response = response;
+ }
+
+ public HttpResponse getResponse() {
+ return this.response;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidationRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidationRequest.java
new file mode 100644
index 000000000..60ad6ca1f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidationRequest.java
@@ -0,0 +1,178 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+
+/**
+ * Class used to represent an asynchronous revalidation event, such as with
+ * "stale-while-revalidate"
+ */
+class AsynchronousValidationRequest implements Runnable {
+ private final AsynchronousValidator parent;
+ private final CachingExec cachingExec;
+ private final HttpRoute route;
+ private final HttpRequestWrapper request;
+ private final HttpClientContext context;
+ private final HttpExecutionAware execAware;
+ private final HttpCacheEntry cacheEntry;
+ private final String identifier;
+ private final int consecutiveFailedAttempts;
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /**
+ * Used internally by {@link AsynchronousValidator} to schedule a
+ * revalidation.
+ * @param request
+ * @param context
+ * @param cacheEntry
+ * @param identifier
+ * @param consecutiveFailedAttempts
+ */
+ AsynchronousValidationRequest(
+ final AsynchronousValidator parent,
+ final CachingExec cachingExec,
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final HttpCacheEntry cacheEntry,
+ final String identifier,
+ final int consecutiveFailedAttempts) {
+ this.parent = parent;
+ this.cachingExec = cachingExec;
+ this.route = route;
+ this.request = request;
+ this.context = context;
+ this.execAware = execAware;
+ this.cacheEntry = cacheEntry;
+ this.identifier = identifier;
+ this.consecutiveFailedAttempts = consecutiveFailedAttempts;
+ }
+
+ public void run() {
+ try {
+ if (revalidateCacheEntry()) {
+ parent.jobSuccessful(identifier);
+ } else {
+ parent.jobFailed(identifier);
+ }
+ } finally {
+ parent.markComplete(identifier);
+ }
+ }
+
+ /**
+ * Revalidate the cache entry and return if the operation was successful.
+ * Success means a connection to the server was established and replay did
+ * not indicate a server error.
+ * @return <code>true</code> if the cache entry was successfully validated;
+ * otherwise <code>false</code>
+ */
+ protected boolean revalidateCacheEntry() {
+ try {
+ final CloseableHttpResponse httpResponse = cachingExec.revalidateCacheEntry(route, request, context, execAware, cacheEntry);
+ try {
+ final int statusCode = httpResponse.getStatusLine().getStatusCode();
+ return isNotServerError(statusCode) && isNotStale(httpResponse);
+ } finally {
+ httpResponse.close();
+ }
+ } catch (final IOException ioe) {
+ log.debug("Asynchronous revalidation failed due to I/O error", ioe);
+ return false;
+ } catch (final HttpException pe) {
+ log.error("HTTP protocol exception during asynchronous revalidation", pe);
+ return false;
+ } catch (final RuntimeException re) {
+ log.error("RuntimeException thrown during asynchronous revalidation: " + re);
+ return false;
+ }
+ }
+
+ /**
+ * Return whether the status code indicates a server error or not.
+ * @param statusCode the status code to be checked
+ * @return if the status code indicates a server error or not
+ */
+ private boolean isNotServerError(final int statusCode) {
+ return statusCode < 500;
+ }
+
+ /**
+ * Try to detect if the returned response is generated from a stale cache entry.
+ * @param httpResponse the response to be checked
+ * @return whether the response is stale or not
+ */
+ private boolean isNotStale(final HttpResponse httpResponse) {
+ final Header[] warnings = httpResponse.getHeaders(HeaderConstants.WARNING);
+ if (warnings != null)
+ {
+ for (final Header warning : warnings)
+ {
+ /**
+ * warn-codes
+ * 110 = Response is stale
+ * 111 = Revalidation failed
+ */
+ final String warningValue = warning.getValue();
+ if (warningValue.startsWith("110") || warningValue.startsWith("111"))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ String getIdentifier() {
+ return identifier;
+ }
+
+ /**
+ * The number of consecutively failed revalidation attempts.
+ * @return the number of consecutively failed revalidation attempts.
+ */
+ public int getConsecutiveFailedAttempts() {
+ return consecutiveFailedAttempts;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidator.java
new file mode 100644
index 000000000..05765a236
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/AsynchronousValidator.java
@@ -0,0 +1,150 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.RejectedExecutionException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+
+/**
+ * Class used for asynchronous revalidations to be used when the "stale-
+ * while-revalidate" directive is present
+ */
+class AsynchronousValidator implements Closeable {
+ private final SchedulingStrategy schedulingStrategy;
+ private final Set<String> queued;
+ private final CacheKeyGenerator cacheKeyGenerator;
+ private final FailureCache failureCache;
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /**
+ * Create AsynchronousValidator which will make revalidation requests
+ * using an {@link ImmediateSchedulingStrategy}. Its thread
+ * pool will be configured according to the given {@link CacheConfig}.
+ * @param config specifies thread pool settings. See
+ * {@link CacheConfig#getAsynchronousWorkersMax()},
+ * {@link CacheConfig#getAsynchronousWorkersCore()},
+ * {@link CacheConfig#getAsynchronousWorkerIdleLifetimeSecs()},
+ * and {@link CacheConfig#getRevalidationQueueSize()}.
+ */
+ public AsynchronousValidator(final CacheConfig config) {
+ this(new ImmediateSchedulingStrategy(config));
+ }
+
+ /**
+ * Create AsynchronousValidator which will make revalidation requests
+ * using the supplied {@link SchedulingStrategy}. Closing the validator
+ * will also close the given schedulingStrategy.
+ * @param schedulingStrategy used to maintain a pool of worker threads and
+ * schedules when requests are executed
+ */
+ AsynchronousValidator(final SchedulingStrategy schedulingStrategy) {
+ this.schedulingStrategy = schedulingStrategy;
+ this.queued = new HashSet<String>();
+ this.cacheKeyGenerator = new CacheKeyGenerator();
+ this.failureCache = new DefaultFailureCache();
+ }
+
+ public void close() throws IOException {
+ schedulingStrategy.close();
+ }
+
+ /**
+ * Schedules an asynchronous revalidation
+ */
+ public synchronized void revalidateCacheEntry(
+ final CachingExec cachingExec,
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final HttpCacheEntry entry) {
+ // getVariantURI will fall back on getURI if no variants exist
+ final String uri = cacheKeyGenerator.getVariantURI(context.getTargetHost(), request, entry);
+
+ if (!queued.contains(uri)) {
+ final int consecutiveFailedAttempts = failureCache.getErrorCount(uri);
+ final AsynchronousValidationRequest revalidationRequest =
+ new AsynchronousValidationRequest(
+ this, cachingExec, route, request, context, execAware, entry, uri, consecutiveFailedAttempts);
+
+ try {
+ schedulingStrategy.schedule(revalidationRequest);
+ queued.add(uri);
+ } catch (final RejectedExecutionException ree) {
+ log.debug("Revalidation for [" + uri + "] not scheduled: " + ree);
+ }
+ }
+ }
+
+ /**
+ * Removes an identifier from the internal list of revalidation jobs in
+ * progress. This is meant to be called by
+ * {@link AsynchronousValidationRequest#run()} once the revalidation is
+ * complete, using the identifier passed in during constructions.
+ * @param identifier
+ */
+ synchronized void markComplete(final String identifier) {
+ queued.remove(identifier);
+ }
+
+ /**
+ * The revalidation job was successful thus the number of consecutive
+ * failed attempts will be reset to zero. Should be called by
+ * {@link AsynchronousValidationRequest#run()}.
+ * @param identifier the revalidation job's unique identifier
+ */
+ void jobSuccessful(final String identifier) {
+ failureCache.resetErrorCount(identifier);
+ }
+
+ /**
+ * The revalidation job did fail and thus the number of consecutive failed
+ * attempts will be increased. Should be called by
+ * {@link AsynchronousValidationRequest#run()}.
+ * @param identifier the revalidation job's unique identifier
+ */
+ void jobFailed(final String identifier) {
+ failureCache.increaseErrorCount(identifier);
+ }
+
+ Set<String> getScheduledIdentifiers() {
+ return Collections.unmodifiableSet(queued);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCache.java
new file mode 100644
index 000000000..4347e173d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCache.java
@@ -0,0 +1,376 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheInvalidator;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheUpdateCallback;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheUpdateException;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.client.cache.ResourceFactory;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.entity.ByteArrayEntity;
+import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+class BasicHttpCache implements HttpCache {
+ private static final Set<String> safeRequestMethods = new HashSet<String>(
+ Arrays.asList(HeaderConstants.HEAD_METHOD,
+ HeaderConstants.GET_METHOD, HeaderConstants.OPTIONS_METHOD,
+ HeaderConstants.TRACE_METHOD));
+
+ private final CacheKeyGenerator uriExtractor;
+ private final ResourceFactory resourceFactory;
+ private final long maxObjectSizeBytes;
+ private final CacheEntryUpdater cacheEntryUpdater;
+ private final CachedHttpResponseGenerator responseGenerator;
+ private final HttpCacheInvalidator cacheInvalidator;
+ private final HttpCacheStorage storage;
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public BasicHttpCache(
+ final ResourceFactory resourceFactory,
+ final HttpCacheStorage storage,
+ final CacheConfig config,
+ final CacheKeyGenerator uriExtractor,
+ final HttpCacheInvalidator cacheInvalidator) {
+ this.resourceFactory = resourceFactory;
+ this.uriExtractor = uriExtractor;
+ this.cacheEntryUpdater = new CacheEntryUpdater(resourceFactory);
+ this.maxObjectSizeBytes = config.getMaxObjectSize();
+ this.responseGenerator = new CachedHttpResponseGenerator();
+ this.storage = storage;
+ this.cacheInvalidator = cacheInvalidator;
+ }
+
+ public BasicHttpCache(
+ final ResourceFactory resourceFactory,
+ final HttpCacheStorage storage,
+ final CacheConfig config,
+ final CacheKeyGenerator uriExtractor) {
+ this( resourceFactory, storage, config, uriExtractor,
+ new CacheInvalidator(uriExtractor, storage));
+ }
+
+ public BasicHttpCache(
+ final ResourceFactory resourceFactory,
+ final HttpCacheStorage storage,
+ final CacheConfig config) {
+ this( resourceFactory, storage, config, new CacheKeyGenerator());
+ }
+
+ public BasicHttpCache(final CacheConfig config) {
+ this(new HeapResourceFactory(), new BasicHttpCacheStorage(config), config);
+ }
+
+ public BasicHttpCache() {
+ this(CacheConfig.DEFAULT);
+ }
+
+ public void flushCacheEntriesFor(final HttpHost host, final HttpRequest request)
+ throws IOException {
+ if (!safeRequestMethods.contains(request.getRequestLine().getMethod())) {
+ final String uri = uriExtractor.getURI(host, request);
+ storage.removeEntry(uri);
+ }
+ }
+
+ public void flushInvalidatedCacheEntriesFor(final HttpHost host, final HttpRequest request, final HttpResponse response) {
+ if (!safeRequestMethods.contains(request.getRequestLine().getMethod())) {
+ cacheInvalidator.flushInvalidatedCacheEntries(host, request, response);
+ }
+ }
+
+ void storeInCache(
+ final HttpHost target, final HttpRequest request, final HttpCacheEntry entry) throws IOException {
+ if (entry.hasVariants()) {
+ storeVariantEntry(target, request, entry);
+ } else {
+ storeNonVariantEntry(target, request, entry);
+ }
+ }
+
+ void storeNonVariantEntry(
+ final HttpHost target, final HttpRequest req, final HttpCacheEntry entry) throws IOException {
+ final String uri = uriExtractor.getURI(target, req);
+ storage.putEntry(uri, entry);
+ }
+
+ void storeVariantEntry(
+ final HttpHost target,
+ final HttpRequest req,
+ final HttpCacheEntry entry) throws IOException {
+ final String parentURI = uriExtractor.getURI(target, req);
+ final String variantURI = uriExtractor.getVariantURI(target, req, entry);
+ storage.putEntry(variantURI, entry);
+
+ final HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
+
+ public HttpCacheEntry update(final HttpCacheEntry existing) throws IOException {
+ return doGetUpdatedParentEntry(
+ req.getRequestLine().getUri(), existing, entry,
+ uriExtractor.getVariantKey(req, entry),
+ variantURI);
+ }
+
+ };
+
+ try {
+ storage.updateEntry(parentURI, callback);
+ } catch (final HttpCacheUpdateException e) {
+ log.warn("Could not update key [" + parentURI + "]", e);
+ }
+ }
+
+ public void reuseVariantEntryFor(final HttpHost target, final HttpRequest req,
+ final Variant variant) throws IOException {
+ final String parentCacheKey = uriExtractor.getURI(target, req);
+ final HttpCacheEntry entry = variant.getEntry();
+ final String variantKey = uriExtractor.getVariantKey(req, entry);
+ final String variantCacheKey = variant.getCacheKey();
+
+ final HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
+ public HttpCacheEntry update(final HttpCacheEntry existing)
+ throws IOException {
+ return doGetUpdatedParentEntry(req.getRequestLine().getUri(),
+ existing, entry, variantKey, variantCacheKey);
+ }
+ };
+
+ try {
+ storage.updateEntry(parentCacheKey, callback);
+ } catch (final HttpCacheUpdateException e) {
+ log.warn("Could not update key [" + parentCacheKey + "]", e);
+ }
+ }
+
+ boolean isIncompleteResponse(final HttpResponse resp, final Resource resource) {
+ final int status = resp.getStatusLine().getStatusCode();
+ if (status != HttpStatus.SC_OK
+ && status != HttpStatus.SC_PARTIAL_CONTENT) {
+ return false;
+ }
+ final Header hdr = resp.getFirstHeader(HTTP.CONTENT_LEN);
+ if (hdr == null) {
+ return false;
+ }
+ final int contentLength;
+ try {
+ contentLength = Integer.parseInt(hdr.getValue());
+ } catch (final NumberFormatException nfe) {
+ return false;
+ }
+ return (resource.length() < contentLength);
+ }
+
+ CloseableHttpResponse generateIncompleteResponseError(
+ final HttpResponse response, final Resource resource) {
+ final int contentLength = Integer.parseInt(response.getFirstHeader(HTTP.CONTENT_LEN).getValue());
+ final HttpResponse error =
+ new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
+ error.setHeader("Content-Type","text/plain;charset=UTF-8");
+ final String msg = String.format("Received incomplete response " +
+ "with Content-Length %d but actual body length %d",
+ contentLength, resource.length());
+ final byte[] msgBytes = msg.getBytes();
+ error.setHeader("Content-Length", Integer.toString(msgBytes.length));
+ error.setEntity(new ByteArrayEntity(msgBytes));
+ return Proxies.enhanceResponse(error);
+ }
+
+ HttpCacheEntry doGetUpdatedParentEntry(
+ final String requestId,
+ final HttpCacheEntry existing,
+ final HttpCacheEntry entry,
+ final String variantKey,
+ final String variantCacheKey) throws IOException {
+ HttpCacheEntry src = existing;
+ if (src == null) {
+ src = entry;
+ }
+
+ Resource resource = null;
+ if (src.getResource() != null) {
+ resource = resourceFactory.copy(requestId, src.getResource());
+ }
+ final Map<String,String> variantMap = new HashMap<String,String>(src.getVariantMap());
+ variantMap.put(variantKey, variantCacheKey);
+ return new HttpCacheEntry(
+ src.getRequestDate(),
+ src.getResponseDate(),
+ src.getStatusLine(),
+ src.getAllHeaders(),
+ resource,
+ variantMap);
+ }
+
+ public HttpCacheEntry updateCacheEntry(final HttpHost target, final HttpRequest request,
+ final HttpCacheEntry stale, final HttpResponse originResponse,
+ final Date requestSent, final Date responseReceived) throws IOException {
+ final HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
+ request.getRequestLine().getUri(),
+ stale,
+ requestSent,
+ responseReceived,
+ originResponse);
+ storeInCache(target, request, updatedEntry);
+ return updatedEntry;
+ }
+
+ public HttpCacheEntry updateVariantCacheEntry(final HttpHost target, final HttpRequest request,
+ final HttpCacheEntry stale, final HttpResponse originResponse,
+ final Date requestSent, final Date responseReceived, final String cacheKey) throws IOException {
+ final HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
+ request.getRequestLine().getUri(),
+ stale,
+ requestSent,
+ responseReceived,
+ originResponse);
+ storage.putEntry(cacheKey, updatedEntry);
+ return updatedEntry;
+ }
+
+ public HttpResponse cacheAndReturnResponse(final HttpHost host, final HttpRequest request,
+ final HttpResponse originResponse, final Date requestSent, final Date responseReceived)
+ throws IOException {
+ return cacheAndReturnResponse(host, request,
+ Proxies.enhanceResponse(originResponse), requestSent,
+ responseReceived);
+ }
+
+ public CloseableHttpResponse cacheAndReturnResponse(
+ final HttpHost host,
+ final HttpRequest request,
+ final CloseableHttpResponse originResponse,
+ final Date requestSent,
+ final Date responseReceived) throws IOException {
+
+ boolean closeOriginResponse = true;
+ final SizeLimitedResponseReader responseReader = getResponseReader(request, originResponse);
+ try {
+ responseReader.readResponse();
+
+ if (responseReader.isLimitReached()) {
+ closeOriginResponse = false;
+ return responseReader.getReconstructedResponse();
+ }
+
+ final Resource resource = responseReader.getResource();
+ if (isIncompleteResponse(originResponse, resource)) {
+ return generateIncompleteResponseError(originResponse, resource);
+ }
+
+ final HttpCacheEntry entry = new HttpCacheEntry(
+ requestSent,
+ responseReceived,
+ originResponse.getStatusLine(),
+ originResponse.getAllHeaders(),
+ resource);
+ storeInCache(host, request, entry);
+ return responseGenerator.generateResponse(entry);
+ } finally {
+ if (closeOriginResponse) {
+ originResponse.close();
+ }
+ }
+ }
+
+ SizeLimitedResponseReader getResponseReader(final HttpRequest request,
+ final CloseableHttpResponse backEndResponse) {
+ return new SizeLimitedResponseReader(
+ resourceFactory, maxObjectSizeBytes, request, backEndResponse);
+ }
+
+ public HttpCacheEntry getCacheEntry(final HttpHost host, final HttpRequest request) throws IOException {
+ final HttpCacheEntry root = storage.getEntry(uriExtractor.getURI(host, request));
+ if (root == null) {
+ return null;
+ }
+ if (!root.hasVariants()) {
+ return root;
+ }
+ final String variantCacheKey = root.getVariantMap().get(uriExtractor.getVariantKey(request, root));
+ if (variantCacheKey == null) {
+ return null;
+ }
+ return storage.getEntry(variantCacheKey);
+ }
+
+ public void flushInvalidatedCacheEntriesFor(final HttpHost host,
+ final HttpRequest request) throws IOException {
+ cacheInvalidator.flushInvalidatedCacheEntries(host, request);
+ }
+
+ public Map<String, Variant> getVariantCacheEntriesWithEtags(final HttpHost host, final HttpRequest request)
+ throws IOException {
+ final Map<String,Variant> variants = new HashMap<String,Variant>();
+ final HttpCacheEntry root = storage.getEntry(uriExtractor.getURI(host, request));
+ if (root == null || !root.hasVariants()) {
+ return variants;
+ }
+ for(final Map.Entry<String, String> variant : root.getVariantMap().entrySet()) {
+ final String variantKey = variant.getKey();
+ final String variantCacheKey = variant.getValue();
+ addVariantWithEtag(variantKey, variantCacheKey, variants);
+ }
+ return variants;
+ }
+
+ private void addVariantWithEtag(final String variantKey,
+ final String variantCacheKey, final Map<String, Variant> variants)
+ throws IOException {
+ final HttpCacheEntry entry = storage.getEntry(variantCacheKey);
+ if (entry == null) {
+ return;
+ }
+ final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
+ if (etagHeader == null) {
+ return;
+ }
+ variants.put(etagHeader.getValue(), new Variant(variantKey, variantCacheKey, entry));
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCacheStorage.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCacheStorage.java
new file mode 100644
index 000000000..225730858
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicHttpCacheStorage.java
@@ -0,0 +1,96 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheUpdateCallback;
+
+/**
+ * Basic {@link HttpCacheStorage} implementation backed by an instance of
+ * {@link java.util.LinkedHashMap}. In other words, cache entries and
+ * the cached response bodies are held in-memory. This cache does NOT
+ * deallocate resources associated with the cache entries; it is intended
+ * for use with {@link HeapResource} and similar. This is the default cache
+ * storage backend used by {@link CachingHttpClients}.
+ *
+ * @since 4.1
+ */
+@ThreadSafe
+public class BasicHttpCacheStorage implements HttpCacheStorage {
+
+ private final CacheMap entries;
+
+ public BasicHttpCacheStorage(final CacheConfig config) {
+ super();
+ this.entries = new CacheMap(config.getMaxCacheEntries());
+ }
+
+ /**
+ * Places a HttpCacheEntry in the cache
+ *
+ * @param url
+ * Url to use as the cache key
+ * @param entry
+ * HttpCacheEntry to place in the cache
+ */
+ public synchronized void putEntry(final String url, final HttpCacheEntry entry) throws IOException {
+ entries.put(url, entry);
+ }
+
+ /**
+ * Gets an entry from the cache, if it exists
+ *
+ * @param url
+ * Url that is the cache key
+ * @return HttpCacheEntry if one exists, or null for cache miss
+ */
+ public synchronized HttpCacheEntry getEntry(final String url) throws IOException {
+ return entries.get(url);
+ }
+
+ /**
+ * Removes a HttpCacheEntry from the cache
+ *
+ * @param url
+ * Url that is the cache key
+ */
+ public synchronized void removeEntry(final String url) throws IOException {
+ entries.remove(url);
+ }
+
+ public synchronized void updateEntry(
+ final String url,
+ final HttpCacheUpdateCallback callback) throws IOException {
+ final HttpCacheEntry existingEntry = entries.get(url);
+ entries.put(url, callback.update(existingEntry));
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicIdGenerator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicIdGenerator.java
new file mode 100644
index 000000000..defdc3999
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/BasicIdGenerator.java
@@ -0,0 +1,86 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Formatter;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+/**
+ * Should produce reasonably unique tokens.
+ */
+@ThreadSafe
+class BasicIdGenerator {
+
+ private final String hostname;
+ private final SecureRandom rnd;
+
+ @GuardedBy("this")
+ private long count;
+
+ public BasicIdGenerator() {
+ super();
+ String hostname;
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch (final UnknownHostException ex) {
+ hostname = "localhost";
+ }
+ this.hostname = hostname;
+ try {
+ this.rnd = SecureRandom.getInstance("SHA1PRNG");
+ } catch (final NoSuchAlgorithmException ex) {
+ throw new Error(ex);
+ }
+ this.rnd.setSeed(System.currentTimeMillis());
+ }
+
+ public synchronized void generate(final StringBuilder buffer) {
+ this.count++;
+ final int rndnum = this.rnd.nextInt();
+ buffer.append(System.currentTimeMillis());
+ buffer.append('.');
+ final Formatter formatter = new Formatter(buffer, Locale.US);
+ formatter.format("%1$016x-%2$08x", this.count, rndnum);
+ formatter.close();
+ buffer.append('.');
+ buffer.append(this.hostname);
+ }
+
+ public String generate() {
+ final StringBuilder buffer = new StringBuilder();
+ generate(buffer);
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheConfig.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheConfig.java
new file mode 100644
index 000000000..964ea2719
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheConfig.java
@@ -0,0 +1,764 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * <p>Java Beans-style configuration for a {@link CachingHttpClient}. Any class
+ * in the caching module that has configuration options should take a
+ * {@link CacheConfig} argument in one of its constructors. A
+ * {@code CacheConfig} instance has sane and conservative defaults, so the
+ * easiest way to specify options is to get an instance and then set just
+ * the options you want to modify from their defaults.</p>
+ *
+ * <p><b>N.B.</b> This class is only for caching-specific configuration; to
+ * configure the behavior of the rest of the client, configure the
+ * {@link ch.boye.httpclientandroidlib.client.HttpClient} used as the &quot;backend&quot;
+ * for the {@code CachingHttpClient}.</p>
+ *
+ * <p>Cache configuration can be grouped into the following categories:</p>
+ *
+ * <p><b>Cache size.</b> If the backend storage supports these limits, you
+ * can specify the {@link CacheConfig#getMaxCacheEntries maximum number of
+ * cache entries} as well as the {@link CacheConfig#getMaxObjectSizeBytes
+ * maximum cacheable response body size}.</p>
+ *
+ * <p><b>Public/private caching.</b> By default, the caching module considers
+ * itself to be a shared (public) cache, and will not, for example, cache
+ * responses to requests with {@code Authorization} headers or responses
+ * marked with {@code Cache-Control: private}. If, however, the cache
+ * is only going to be used by one logical "user" (behaving similarly to a
+ * browser cache), then you will want to {@link
+ * CacheConfig#setSharedCache(boolean) turn off the shared cache setting}.</p>
+ *
+ * <p><b>303 caching</b>. RFC2616 explicitly disallows caching 303 responses;
+ * however, the HTTPbis working group says they can be cached
+ * if explicitly indicated in the response headers and permitted by the request method.
+ * (They also indicate that disallowing 303 caching is actually an unintended
+ * spec error in RFC2616).
+ * This behavior is off by default, to err on the side of a conservative
+ * adherence to the existing standard, but you may want to
+ * {@link Builder#setAllow303Caching(boolean) enable it}.
+ *
+ * <p><b>Weak ETags on PUT/DELETE If-Match requests</b>. RFC2616 explicitly
+ * prohibits the use of weak validators in non-GET requests, however, the
+ * HTTPbis working group says while the limitation for weak validators on ranged
+ * requests makes sense, weak ETag validation is useful on full non-GET
+ * requests; e.g., PUT with If-Match. This behavior is off by default, to err on
+ * the side of a conservative adherence to the existing standard, but you may
+ * want to {@link Builder#setWeakETagOnPutDeleteAllowed(boolean) enable it}.
+ *
+ * <p><b>Heuristic caching</b>. Per RFC2616, a cache may cache certain cache
+ * entries even if no explicit cache control headers are set by the origin.
+ * This behavior is off by default, but you may want to turn this on if you
+ * are working with an origin that doesn't set proper headers but where you
+ * still want to cache the responses. You will want to {@link
+ * CacheConfig#setHeuristicCachingEnabled(boolean) enable heuristic caching},
+ * then specify either a {@link CacheConfig#getHeuristicDefaultLifetime()
+ * default freshness lifetime} and/or a {@link
+ * CacheConfig#setHeuristicCoefficient(float) fraction of the time since
+ * the resource was last modified}. See Sections
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.2">
+ * 13.2.2</a> and <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.4">
+ * 13.2.4</a> of the HTTP/1.1 RFC for more details on heuristic caching.</p>
+ *
+ * <p><b>Background validation</b>. The cache module supports the
+ * {@code stale-while-revalidate} directive of
+ * <a href="http://tools.ietf.org/html/rfc5861">RFC5861</a>, which allows
+ * certain cache entry revalidations to happen in the background. You may
+ * want to tweak the settings for the {@link
+ * CacheConfig#getAsynchronousWorkersCore() minimum} and {@link
+ * CacheConfig#getAsynchronousWorkersMax() maximum} number of background
+ * worker threads, as well as the {@link
+ * CacheConfig#getAsynchronousWorkerIdleLifetimeSecs() maximum time they
+ * can be idle before being reclaimed}. You can also control the {@link
+ * CacheConfig#getRevalidationQueueSize() size of the queue} used for
+ * revalidations when there aren't enough workers to keep up with demand.</b>
+ */
+public class CacheConfig implements Cloneable {
+
+ /** Default setting for the maximum object size that will be
+ * cached, in bytes.
+ */
+ public final static int DEFAULT_MAX_OBJECT_SIZE_BYTES = 8192;
+
+ /** Default setting for the maximum number of cache entries
+ * that will be retained.
+ */
+ public final static int DEFAULT_MAX_CACHE_ENTRIES = 1000;
+
+ /** Default setting for the number of retries on a failed
+ * cache update
+ */
+ public final static int DEFAULT_MAX_UPDATE_RETRIES = 1;
+
+ /** Default setting for 303 caching
+ */
+ public final static boolean DEFAULT_303_CACHING_ENABLED = false;
+
+ /** Default setting to allow weak tags on PUT/DELETE methods
+ */
+ public final static boolean DEFAULT_WEAK_ETAG_ON_PUTDELETE_ALLOWED = false;
+
+ /** Default setting for heuristic caching
+ */
+ public final static boolean DEFAULT_HEURISTIC_CACHING_ENABLED = false;
+
+ /** Default coefficient used to heuristically determine freshness
+ * lifetime from the Last-Modified time of a cache entry.
+ */
+ public final static float DEFAULT_HEURISTIC_COEFFICIENT = 0.1f;
+
+ /** Default lifetime in seconds to be assumed when we cannot calculate
+ * freshness heuristically.
+ */
+ public final static long DEFAULT_HEURISTIC_LIFETIME = 0;
+
+ /** Default number of worker threads to allow for background revalidations
+ * resulting from the stale-while-revalidate directive.
+ */
+ public static final int DEFAULT_ASYNCHRONOUS_WORKERS_MAX = 1;
+
+ /** Default minimum number of worker threads to allow for background
+ * revalidations resulting from the stale-while-revalidate directive.
+ */
+ public static final int DEFAULT_ASYNCHRONOUS_WORKERS_CORE = 1;
+
+ /** Default maximum idle lifetime for a background revalidation thread
+ * before it gets reclaimed.
+ */
+ public static final int DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS = 60;
+
+ /** Default maximum queue length for background revalidation requests.
+ */
+ public static final int DEFAULT_REVALIDATION_QUEUE_SIZE = 100;
+
+ public static final CacheConfig DEFAULT = new Builder().build();
+
+ // TODO: make final
+ private long maxObjectSize;
+ private int maxCacheEntries;
+ private int maxUpdateRetries;
+ private boolean allow303Caching;
+ private boolean weakETagOnPutDeleteAllowed;
+ private boolean heuristicCachingEnabled;
+ private float heuristicCoefficient;
+ private long heuristicDefaultLifetime;
+ private boolean isSharedCache;
+ private int asynchronousWorkersMax;
+ private int asynchronousWorkersCore;
+ private int asynchronousWorkerIdleLifetimeSecs;
+ private int revalidationQueueSize;
+ private boolean neverCacheHTTP10ResponsesWithQuery;
+
+ /**
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public CacheConfig() {
+ super();
+ this.maxObjectSize = DEFAULT_MAX_OBJECT_SIZE_BYTES;
+ this.maxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
+ this.maxUpdateRetries = DEFAULT_MAX_UPDATE_RETRIES;
+ this.allow303Caching = DEFAULT_303_CACHING_ENABLED;
+ this.weakETagOnPutDeleteAllowed = DEFAULT_WEAK_ETAG_ON_PUTDELETE_ALLOWED;
+ this.heuristicCachingEnabled = DEFAULT_HEURISTIC_CACHING_ENABLED;
+ this.heuristicCoefficient = DEFAULT_HEURISTIC_COEFFICIENT;
+ this.heuristicDefaultLifetime = DEFAULT_HEURISTIC_LIFETIME;
+ this.isSharedCache = true;
+ this.asynchronousWorkersMax = DEFAULT_ASYNCHRONOUS_WORKERS_MAX;
+ this.asynchronousWorkersCore = DEFAULT_ASYNCHRONOUS_WORKERS_CORE;
+ this.asynchronousWorkerIdleLifetimeSecs = DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS;
+ this.revalidationQueueSize = DEFAULT_REVALIDATION_QUEUE_SIZE;
+ }
+
+ CacheConfig(
+ final long maxObjectSize,
+ final int maxCacheEntries,
+ final int maxUpdateRetries,
+ final boolean allow303Caching,
+ final boolean weakETagOnPutDeleteAllowed,
+ final boolean heuristicCachingEnabled,
+ final float heuristicCoefficient,
+ final long heuristicDefaultLifetime,
+ final boolean isSharedCache,
+ final int asynchronousWorkersMax,
+ final int asynchronousWorkersCore,
+ final int asynchronousWorkerIdleLifetimeSecs,
+ final int revalidationQueueSize,
+ final boolean neverCacheHTTP10ResponsesWithQuery) {
+ super();
+ this.maxObjectSize = maxObjectSize;
+ this.maxCacheEntries = maxCacheEntries;
+ this.maxUpdateRetries = maxUpdateRetries;
+ this.allow303Caching = allow303Caching;
+ this.weakETagOnPutDeleteAllowed = weakETagOnPutDeleteAllowed;
+ this.heuristicCachingEnabled = heuristicCachingEnabled;
+ this.heuristicCoefficient = heuristicCoefficient;
+ this.heuristicDefaultLifetime = heuristicDefaultLifetime;
+ this.isSharedCache = isSharedCache;
+ this.asynchronousWorkersMax = asynchronousWorkersMax;
+ this.asynchronousWorkersCore = asynchronousWorkersCore;
+ this.asynchronousWorkerIdleLifetimeSecs = asynchronousWorkerIdleLifetimeSecs;
+ this.revalidationQueueSize = revalidationQueueSize;
+ }
+
+ /**
+ * Returns the current maximum response body size that will be cached.
+ * @return size in bytes
+ *
+ * @deprecated (4.2) use {@link #getMaxObjectSize()}
+ */
+ @Deprecated
+ public int getMaxObjectSizeBytes() {
+ return maxObjectSize > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) maxObjectSize;
+ }
+
+ /**
+ * Specifies the maximum response body size that will be eligible for caching.
+ * @param maxObjectSizeBytes size in bytes
+ *
+ * @deprecated (4.2) use {@link Builder}.
+ */
+ @Deprecated
+ public void setMaxObjectSizeBytes(final int maxObjectSizeBytes) {
+ if (maxObjectSizeBytes > Integer.MAX_VALUE) {
+ this.maxObjectSize = Integer.MAX_VALUE;
+ } else {
+ this.maxObjectSize = maxObjectSizeBytes;
+ }
+ }
+
+ /**
+ * Returns the current maximum response body size that will be cached.
+ * @return size in bytes
+ *
+ * @since 4.2
+ */
+ public long getMaxObjectSize() {
+ return maxObjectSize;
+ }
+
+ /**
+ * Specifies the maximum response body size that will be eligible for caching.
+ * @param maxObjectSize size in bytes
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setMaxObjectSize(final long maxObjectSize) {
+ this.maxObjectSize = maxObjectSize;
+ }
+
+ /**
+ * Returns whether the cache will never cache HTTP 1.0 responses with a query string or not.
+ * @return {@code true} to not cache query string responses, {@code false} to cache if explicit cache headers are
+ * found
+ */
+ public boolean isNeverCacheHTTP10ResponsesWithQuery() {
+ return neverCacheHTTP10ResponsesWithQuery;
+ }
+
+ /**
+ * Returns the maximum number of cache entries the cache will retain.
+ */
+ public int getMaxCacheEntries() {
+ return maxCacheEntries;
+ }
+
+ /**
+ * Sets the maximum number of cache entries the cache will retain.
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setMaxCacheEntries(final int maxCacheEntries) {
+ this.maxCacheEntries = maxCacheEntries;
+ }
+
+ /**
+ * Returns the number of times to retry a cache update on failure
+ */
+ public int getMaxUpdateRetries(){
+ return maxUpdateRetries;
+ }
+
+ /**
+ * Sets the number of times to retry a cache update on failure
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setMaxUpdateRetries(final int maxUpdateRetries){
+ this.maxUpdateRetries = maxUpdateRetries;
+ }
+
+ /**
+ * Returns whether 303 caching is enabled.
+ * @return {@code true} if it is enabled.
+ */
+ public boolean is303CachingEnabled() {
+ return allow303Caching;
+ }
+
+ /**
+ * Returns whether weak etags is allowed with PUT/DELETE methods.
+ * @return {@code true} if it is allowed.
+ */
+ public boolean isWeakETagOnPutDeleteAllowed() {
+ return weakETagOnPutDeleteAllowed;
+ }
+
+ /**
+ * Returns whether heuristic caching is enabled.
+ * @return {@code true} if it is enabled.
+ */
+ public boolean isHeuristicCachingEnabled() {
+ return heuristicCachingEnabled;
+ }
+
+ /**
+ * Enables or disables heuristic caching.
+ * @param heuristicCachingEnabled should be {@code true} to
+ * permit heuristic caching, {@code false} to disable it.
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setHeuristicCachingEnabled(final boolean heuristicCachingEnabled) {
+ this.heuristicCachingEnabled = heuristicCachingEnabled;
+ }
+
+ /**
+ * Returns lifetime coefficient used in heuristic freshness caching.
+ */
+ public float getHeuristicCoefficient() {
+ return heuristicCoefficient;
+ }
+
+ /**
+ * Sets coefficient to be used in heuristic freshness caching. This is
+ * interpreted as the fraction of the time between the {@code Last-Modified}
+ * and {@code Date} headers of a cached response during which the cached
+ * response will be considered heuristically fresh.
+ * @param heuristicCoefficient should be between {@code 0.0} and
+ * {@code 1.0}.
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setHeuristicCoefficient(final float heuristicCoefficient) {
+ this.heuristicCoefficient = heuristicCoefficient;
+ }
+
+ /**
+ * Get the default lifetime to be used if heuristic freshness calculation is
+ * not possible.
+ */
+ public long getHeuristicDefaultLifetime() {
+ return heuristicDefaultLifetime;
+ }
+
+ /**
+ * Sets default lifetime in seconds to be used if heuristic freshness
+ * calculation is not possible. Explicit cache control directives on
+ * either the request or origin response will override this, as will
+ * the heuristic {@code Last-Modified} freshness calculation if it is
+ * available.
+ * @param heuristicDefaultLifetimeSecs is the number of seconds to
+ * consider a cache-eligible response fresh in the absence of other
+ * information. Set this to {@code 0} to disable this style of
+ * heuristic caching.
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setHeuristicDefaultLifetime(final long heuristicDefaultLifetimeSecs) {
+ this.heuristicDefaultLifetime = heuristicDefaultLifetimeSecs;
+ }
+
+ /**
+ * Returns whether the cache will behave as a shared cache or not.
+ * @return {@code true} for a shared cache, {@code false} for a non-
+ * shared (private) cache
+ */
+ public boolean isSharedCache() {
+ return isSharedCache;
+ }
+
+ /**
+ * Sets whether the cache should behave as a shared cache or not.
+ * @param isSharedCache true to behave as a shared cache, false to
+ * behave as a non-shared (private) cache. To have the cache
+ * behave like a browser cache, you want to set this to {@code false}.
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setSharedCache(final boolean isSharedCache) {
+ this.isSharedCache = isSharedCache;
+ }
+
+ /**
+ * Returns the maximum number of threads to allow for background
+ * revalidations due to the {@code stale-while-revalidate} directive. A
+ * value of 0 means background revalidations are disabled.
+ */
+ public int getAsynchronousWorkersMax() {
+ return asynchronousWorkersMax;
+ }
+
+ /**
+ * Sets the maximum number of threads to allow for background
+ * revalidations due to the {@code stale-while-revalidate} directive.
+ * @param max number of threads; a value of 0 disables background
+ * revalidations.
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setAsynchronousWorkersMax(final int max) {
+ this.asynchronousWorkersMax = max;
+ }
+
+ /**
+ * Returns the minimum number of threads to keep alive for background
+ * revalidations due to the {@code stale-while-revalidate} directive.
+ */
+ public int getAsynchronousWorkersCore() {
+ return asynchronousWorkersCore;
+ }
+
+ /**
+ * Sets the minimum number of threads to keep alive for background
+ * revalidations due to the {@code stale-while-revalidate} directive.
+ * @param min should be greater than zero and less than or equal
+ * to <code>getAsynchronousWorkersMax()</code>
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setAsynchronousWorkersCore(final int min) {
+ this.asynchronousWorkersCore = min;
+ }
+
+ /**
+ * Returns the current maximum idle lifetime in seconds for a
+ * background revalidation worker thread. If a worker thread is idle
+ * for this long, and there are more than the core number of worker
+ * threads alive, the worker will be reclaimed.
+ */
+ public int getAsynchronousWorkerIdleLifetimeSecs() {
+ return asynchronousWorkerIdleLifetimeSecs;
+ }
+
+ /**
+ * Sets the current maximum idle lifetime in seconds for a
+ * background revalidation worker thread. If a worker thread is idle
+ * for this long, and there are more than the core number of worker
+ * threads alive, the worker will be reclaimed.
+ * @param secs idle lifetime in seconds
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setAsynchronousWorkerIdleLifetimeSecs(final int secs) {
+ this.asynchronousWorkerIdleLifetimeSecs = secs;
+ }
+
+ /**
+ * Returns the current maximum queue size for background revalidations.
+ */
+ public int getRevalidationQueueSize() {
+ return revalidationQueueSize;
+ }
+
+ /**
+ * Sets the current maximum queue size for background revalidations.
+ *
+ * @deprecated (4.3) use {@link Builder}.
+ */
+ @Deprecated
+ public void setRevalidationQueueSize(final int size) {
+ this.revalidationQueueSize = size;
+ }
+
+ @Override
+ protected CacheConfig clone() throws CloneNotSupportedException {
+ return (CacheConfig) super.clone();
+ }
+
+ public static Builder custom() {
+ return new Builder();
+ }
+
+ public static Builder copy(final CacheConfig config) {
+ Args.notNull(config, "Cache config");
+ return new Builder()
+ .setMaxObjectSize(config.getMaxObjectSize())
+ .setMaxCacheEntries(config.getMaxCacheEntries())
+ .setMaxUpdateRetries(config.getMaxUpdateRetries())
+ .setHeuristicCachingEnabled(config.isHeuristicCachingEnabled())
+ .setHeuristicCoefficient(config.getHeuristicCoefficient())
+ .setHeuristicDefaultLifetime(config.getHeuristicDefaultLifetime())
+ .setSharedCache(config.isSharedCache())
+ .setAsynchronousWorkersMax(config.getAsynchronousWorkersMax())
+ .setAsynchronousWorkersCore(config.getAsynchronousWorkersCore())
+ .setAsynchronousWorkerIdleLifetimeSecs(config.getAsynchronousWorkerIdleLifetimeSecs())
+ .setRevalidationQueueSize(config.getRevalidationQueueSize())
+ .setNeverCacheHTTP10ResponsesWithQueryString(config.isNeverCacheHTTP10ResponsesWithQuery());
+ }
+
+
+ public static class Builder {
+
+ private long maxObjectSize;
+ private int maxCacheEntries;
+ private int maxUpdateRetries;
+ private boolean allow303Caching;
+ private boolean weakETagOnPutDeleteAllowed;
+ private boolean heuristicCachingEnabled;
+ private float heuristicCoefficient;
+ private long heuristicDefaultLifetime;
+ private boolean isSharedCache;
+ private int asynchronousWorkersMax;
+ private int asynchronousWorkersCore;
+ private int asynchronousWorkerIdleLifetimeSecs;
+ private int revalidationQueueSize;
+ private boolean neverCacheHTTP10ResponsesWithQuery;
+
+ Builder() {
+ this.maxObjectSize = DEFAULT_MAX_OBJECT_SIZE_BYTES;
+ this.maxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
+ this.maxUpdateRetries = DEFAULT_MAX_UPDATE_RETRIES;
+ this.allow303Caching = DEFAULT_303_CACHING_ENABLED;
+ this.weakETagOnPutDeleteAllowed = DEFAULT_WEAK_ETAG_ON_PUTDELETE_ALLOWED;
+ this.heuristicCachingEnabled = false;
+ this.heuristicCoefficient = DEFAULT_HEURISTIC_COEFFICIENT;
+ this.heuristicDefaultLifetime = DEFAULT_HEURISTIC_LIFETIME;
+ this.isSharedCache = true;
+ this.asynchronousWorkersMax = DEFAULT_ASYNCHRONOUS_WORKERS_MAX;
+ this.asynchronousWorkersCore = DEFAULT_ASYNCHRONOUS_WORKERS_CORE;
+ this.asynchronousWorkerIdleLifetimeSecs = DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS;
+ this.revalidationQueueSize = DEFAULT_REVALIDATION_QUEUE_SIZE;
+ }
+
+ /**
+ * Specifies the maximum response body size that will be eligible for caching.
+ * @param maxObjectSize size in bytes
+ */
+ public Builder setMaxObjectSize(final long maxObjectSize) {
+ this.maxObjectSize = maxObjectSize;
+ return this;
+ }
+
+ /**
+ * Sets the maximum number of cache entries the cache will retain.
+ */
+ public Builder setMaxCacheEntries(final int maxCacheEntries) {
+ this.maxCacheEntries = maxCacheEntries;
+ return this;
+ }
+
+ /**
+ * Sets the number of times to retry a cache update on failure
+ */
+ public Builder setMaxUpdateRetries(final int maxUpdateRetries) {
+ this.maxUpdateRetries = maxUpdateRetries;
+ return this;
+ }
+
+ /**
+ * Enables or disables 303 caching.
+ * @param allow303Caching should be {@code true} to
+ * permit 303 caching, {@code false} to disable it.
+ */
+ public Builder setAllow303Caching(final boolean allow303Caching) {
+ this.allow303Caching = allow303Caching;
+ return this;
+ }
+
+ /**
+ * Allows or disallows weak etags to be used with PUT/DELETE If-Match requests.
+ * @param weakETagOnPutDeleteAllowed should be {@code true} to
+ * permit weak etags, {@code false} to reject them.
+ */
+ public Builder setWeakETagOnPutDeleteAllowed(final boolean weakETagOnPutDeleteAllowed) {
+ this.weakETagOnPutDeleteAllowed = weakETagOnPutDeleteAllowed;
+ return this;
+ }
+
+ /**
+ * Enables or disables heuristic caching.
+ * @param heuristicCachingEnabled should be {@code true} to
+ * permit heuristic caching, {@code false} to enable it.
+ */
+ public Builder setHeuristicCachingEnabled(final boolean heuristicCachingEnabled) {
+ this.heuristicCachingEnabled = heuristicCachingEnabled;
+ return this;
+ }
+
+ /**
+ * Sets coefficient to be used in heuristic freshness caching. This is
+ * interpreted as the fraction of the time between the {@code Last-Modified}
+ * and {@code Date} headers of a cached response during which the cached
+ * response will be considered heuristically fresh.
+ * @param heuristicCoefficient should be between {@code 0.0} and
+ * {@code 1.0}.
+ */
+ public Builder setHeuristicCoefficient(final float heuristicCoefficient) {
+ this.heuristicCoefficient = heuristicCoefficient;
+ return this;
+ }
+
+ /**
+ * Sets default lifetime in seconds to be used if heuristic freshness
+ * calculation is not possible. Explicit cache control directives on
+ * either the request or origin response will override this, as will
+ * the heuristic {@code Last-Modified} freshness calculation if it is
+ * available.
+ * @param heuristicDefaultLifetime is the number of seconds to
+ * consider a cache-eligible response fresh in the absence of other
+ * information. Set this to {@code 0} to disable this style of
+ * heuristic caching.
+ */
+ public Builder setHeuristicDefaultLifetime(final long heuristicDefaultLifetime) {
+ this.heuristicDefaultLifetime = heuristicDefaultLifetime;
+ return this;
+ }
+
+ /**
+ * Sets whether the cache should behave as a shared cache or not.
+ * @param isSharedCache true to behave as a shared cache, false to
+ * behave as a non-shared (private) cache. To have the cache
+ * behave like a browser cache, you want to set this to {@code false}.
+ */
+ public Builder setSharedCache(final boolean isSharedCache) {
+ this.isSharedCache = isSharedCache;
+ return this;
+ }
+
+ /**
+ * Sets the maximum number of threads to allow for background
+ * revalidations due to the {@code stale-while-revalidate} directive.
+ * @param asynchronousWorkersMax number of threads; a value of 0 disables background
+ * revalidations.
+ */
+ public Builder setAsynchronousWorkersMax(final int asynchronousWorkersMax) {
+ this.asynchronousWorkersMax = asynchronousWorkersMax;
+ return this;
+ }
+
+ /**
+ * Sets the minimum number of threads to keep alive for background
+ * revalidations due to the {@code stale-while-revalidate} directive.
+ * @param asynchronousWorkersCore should be greater than zero and less than or equal
+ * to <code>getAsynchronousWorkersMax()</code>
+ */
+ public Builder setAsynchronousWorkersCore(final int asynchronousWorkersCore) {
+ this.asynchronousWorkersCore = asynchronousWorkersCore;
+ return this;
+ }
+
+ /**
+ * Sets the current maximum idle lifetime in seconds for a
+ * background revalidation worker thread. If a worker thread is idle
+ * for this long, and there are more than the core number of worker
+ * threads alive, the worker will be reclaimed.
+ * @param asynchronousWorkerIdleLifetimeSecs idle lifetime in seconds
+ */
+ public Builder setAsynchronousWorkerIdleLifetimeSecs(final int asynchronousWorkerIdleLifetimeSecs) {
+ this.asynchronousWorkerIdleLifetimeSecs = asynchronousWorkerIdleLifetimeSecs;
+ return this;
+ }
+
+ /**
+ * Sets the current maximum queue size for background revalidations.
+ */
+ public Builder setRevalidationQueueSize(final int revalidationQueueSize) {
+ this.revalidationQueueSize = revalidationQueueSize;
+ return this;
+ }
+
+ /**
+ * Sets whether the cache should never cache HTTP 1.0 responses with a query string or not.
+ * @param neverCacheHTTP10ResponsesWithQuery true to never cache responses with a query
+ * string, false to cache if explicit cache headers are found. Set this to {@code true}
+ * to better emulate IE, which also never caches responses, regardless of what caching
+ * headers may be present.
+ */
+ public Builder setNeverCacheHTTP10ResponsesWithQueryString(
+ final boolean neverCacheHTTP10ResponsesWithQuery) {
+ this.neverCacheHTTP10ResponsesWithQuery = neverCacheHTTP10ResponsesWithQuery;
+ return this;
+ }
+
+ public CacheConfig build() {
+ return new CacheConfig(
+ maxObjectSize,
+ maxCacheEntries,
+ maxUpdateRetries,
+ allow303Caching,
+ weakETagOnPutDeleteAllowed,
+ heuristicCachingEnabled,
+ heuristicCoefficient,
+ heuristicDefaultLifetime,
+ isSharedCache,
+ asynchronousWorkersMax,
+ asynchronousWorkersCore,
+ asynchronousWorkerIdleLifetimeSecs,
+ revalidationQueueSize,
+ neverCacheHTTP10ResponsesWithQuery);
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[maxObjectSize=").append(this.maxObjectSize)
+ .append(", maxCacheEntries=").append(this.maxCacheEntries)
+ .append(", maxUpdateRetries=").append(this.maxUpdateRetries)
+ .append(", 303CachingEnabled=").append(this.allow303Caching)
+ .append(", weakETagOnPutDeleteAllowed=").append(this.weakETagOnPutDeleteAllowed)
+ .append(", heuristicCachingEnabled=").append(this.heuristicCachingEnabled)
+ .append(", heuristicCoefficient=").append(this.heuristicCoefficient)
+ .append(", heuristicDefaultLifetime=").append(this.heuristicDefaultLifetime)
+ .append(", isSharedCache=").append(this.isSharedCache)
+ .append(", asynchronousWorkersMax=").append(this.asynchronousWorkersMax)
+ .append(", asynchronousWorkersCore=").append(this.asynchronousWorkersCore)
+ .append(", asynchronousWorkerIdleLifetimeSecs=").append(this.asynchronousWorkerIdleLifetimeSecs)
+ .append(", revalidationQueueSize=").append(this.revalidationQueueSize)
+ .append(", neverCacheHTTP10ResponsesWithQuery=").append(this.neverCacheHTTP10ResponsesWithQuery)
+ .append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntity.java
new file mode 100644
index 000000000..1906166d1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntity.java
@@ -0,0 +1,99 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+@Immutable
+class CacheEntity implements HttpEntity, Serializable {
+
+ private static final long serialVersionUID = -3467082284120936233L;
+
+ private final HttpCacheEntry cacheEntry;
+
+ public CacheEntity(final HttpCacheEntry cacheEntry) {
+ super();
+ this.cacheEntry = cacheEntry;
+ }
+
+ public Header getContentType() {
+ return this.cacheEntry.getFirstHeader(HTTP.CONTENT_TYPE);
+ }
+
+ public Header getContentEncoding() {
+ return this.cacheEntry.getFirstHeader(HTTP.CONTENT_ENCODING);
+ }
+
+ public boolean isChunked() {
+ return false;
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public long getContentLength() {
+ return this.cacheEntry.getResource().length();
+ }
+
+ public InputStream getContent() throws IOException {
+ return this.cacheEntry.getResource().getInputStream();
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ final InputStream instream = this.cacheEntry.getResource().getInputStream();
+ try {
+ IOUtils.copy(instream, outstream);
+ } finally {
+ instream.close();
+ }
+ }
+
+ public boolean isStreaming() {
+ return false;
+ }
+
+ public void consumeContent() throws IOException {
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntryUpdater.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntryUpdater.java
new file mode 100644
index 000000000..381a7508d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheEntryUpdater.java
@@ -0,0 +1,173 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.ListIterator;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.client.cache.ResourceFactory;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Update a {@link HttpCacheEntry} with new or updated information based on the latest
+ * 304 status response from the Server. Use the {@link HttpResponse} to perform
+ * the update.
+ *
+ * @since 4.1
+ */
+@Immutable
+class CacheEntryUpdater {
+
+ private final ResourceFactory resourceFactory;
+
+ CacheEntryUpdater() {
+ this(new HeapResourceFactory());
+ }
+
+ CacheEntryUpdater(final ResourceFactory resourceFactory) {
+ super();
+ this.resourceFactory = resourceFactory;
+ }
+
+ /**
+ * Update the entry with the new information from the response. Should only be used for
+ * 304 responses.
+ *
+ * @param requestId
+ * @param entry The cache Entry to be updated
+ * @param requestDate When the request was performed
+ * @param responseDate When the response was gotten
+ * @param response The HttpResponse from the backend server call
+ * @return HttpCacheEntry an updated version of the cache entry
+ * @throws java.io.IOException if something bad happens while trying to read the body from the original entry
+ */
+ public HttpCacheEntry updateCacheEntry(
+ final String requestId,
+ final HttpCacheEntry entry,
+ final Date requestDate,
+ final Date responseDate,
+ final HttpResponse response) throws IOException {
+ Args.check(response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED,
+ "Response must have 304 status code");
+ final Header[] mergedHeaders = mergeHeaders(entry, response);
+ Resource resource = null;
+ if (entry.getResource() != null) {
+ resource = resourceFactory.copy(requestId, entry.getResource());
+ }
+ return new HttpCacheEntry(
+ requestDate,
+ responseDate,
+ entry.getStatusLine(),
+ mergedHeaders,
+ resource);
+ }
+
+ protected Header[] mergeHeaders(final HttpCacheEntry entry, final HttpResponse response) {
+
+ if (entryAndResponseHaveDateHeader(entry, response)
+ && entryDateHeaderNewerThenResponse(entry, response)) {
+ // Don't merge headers, keep the entry's headers as they are newer.
+ return entry.getAllHeaders();
+ }
+
+ final List<Header> cacheEntryHeaderList = new ArrayList<Header>(Arrays.asList(entry
+ .getAllHeaders()));
+ removeCacheHeadersThatMatchResponse(cacheEntryHeaderList, response);
+ removeCacheEntry1xxWarnings(cacheEntryHeaderList, entry);
+ cacheEntryHeaderList.addAll(Arrays.asList(response.getAllHeaders()));
+
+ return cacheEntryHeaderList.toArray(new Header[cacheEntryHeaderList.size()]);
+ }
+
+ private void removeCacheHeadersThatMatchResponse(final List<Header> cacheEntryHeaderList,
+ final HttpResponse response) {
+ for (final Header responseHeader : response.getAllHeaders()) {
+ final ListIterator<Header> cacheEntryHeaderListIter = cacheEntryHeaderList.listIterator();
+
+ while (cacheEntryHeaderListIter.hasNext()) {
+ final String cacheEntryHeaderName = cacheEntryHeaderListIter.next().getName();
+
+ if (cacheEntryHeaderName.equals(responseHeader.getName())) {
+ cacheEntryHeaderListIter.remove();
+ }
+ }
+ }
+ }
+
+ private void removeCacheEntry1xxWarnings(final List<Header> cacheEntryHeaderList, final HttpCacheEntry entry) {
+ final ListIterator<Header> cacheEntryHeaderListIter = cacheEntryHeaderList.listIterator();
+
+ while (cacheEntryHeaderListIter.hasNext()) {
+ final String cacheEntryHeaderName = cacheEntryHeaderListIter.next().getName();
+
+ if (HeaderConstants.WARNING.equals(cacheEntryHeaderName)) {
+ for (final Header cacheEntryWarning : entry.getHeaders(HeaderConstants.WARNING)) {
+ if (cacheEntryWarning.getValue().startsWith("1")) {
+ cacheEntryHeaderListIter.remove();
+ }
+ }
+ }
+ }
+ }
+
+ private boolean entryDateHeaderNewerThenResponse(final HttpCacheEntry entry, final HttpResponse response) {
+ final Date entryDate = DateUtils.parseDate(entry.getFirstHeader(HTTP.DATE_HEADER)
+ .getValue());
+ final Date responseDate = DateUtils.parseDate(response.getFirstHeader(HTTP.DATE_HEADER)
+ .getValue());
+ if (entryDate == null || responseDate == null) {
+ return false;
+ }
+ if (!entryDate.after(responseDate)) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean entryAndResponseHaveDateHeader(final HttpCacheEntry entry, final HttpResponse response) {
+ if (entry.getFirstHeader(HTTP.DATE_HEADER) != null
+ && response.getFirstHeader(HTTP.DATE_HEADER) != null) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheInvalidator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheInvalidator.java
new file mode 100644
index 000000000..19e62869e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheInvalidator.java
@@ -0,0 +1,288 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Date;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheInvalidator;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * Given a particular HttpRequest, flush any cache entries that this request
+ * would invalidate.
+ *
+ * @since 4.1
+ */
+@Immutable
+class CacheInvalidator implements HttpCacheInvalidator {
+
+ private final HttpCacheStorage storage;
+ private final CacheKeyGenerator cacheKeyGenerator;
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /**
+ * Create a new {@link CacheInvalidator} for a given {@link HttpCache} and
+ * {@link CacheKeyGenerator}.
+ *
+ * @param uriExtractor Provides identifiers for the keys to store cache entries
+ * @param storage the cache to store items away in
+ */
+ public CacheInvalidator(
+ final CacheKeyGenerator uriExtractor,
+ final HttpCacheStorage storage) {
+ this.cacheKeyGenerator = uriExtractor;
+ this.storage = storage;
+ }
+
+ /**
+ * Remove cache entries from the cache that are no longer fresh or
+ * have been invalidated in some way.
+ *
+ * @param host The backend host we are talking to
+ * @param req The HttpRequest to that host
+ */
+ public void flushInvalidatedCacheEntries(final HttpHost host, final HttpRequest req) {
+ if (requestShouldNotBeCached(req)) {
+ log.debug("Request should not be cached");
+
+ final String theUri = cacheKeyGenerator.getURI(host, req);
+
+ final HttpCacheEntry parent = getEntry(theUri);
+
+ log.debug("parent entry: " + parent);
+
+ if (parent != null) {
+ for (final String variantURI : parent.getVariantMap().values()) {
+ flushEntry(variantURI);
+ }
+ flushEntry(theUri);
+ }
+ final URL reqURL = getAbsoluteURL(theUri);
+ if (reqURL == null) {
+ log.error("Couldn't transform request into valid URL");
+ return;
+ }
+ final Header clHdr = req.getFirstHeader("Content-Location");
+ if (clHdr != null) {
+ final String contentLocation = clHdr.getValue();
+ if (!flushAbsoluteUriFromSameHost(reqURL, contentLocation)) {
+ flushRelativeUriFromSameHost(reqURL, contentLocation);
+ }
+ }
+ final Header lHdr = req.getFirstHeader("Location");
+ if (lHdr != null) {
+ flushAbsoluteUriFromSameHost(reqURL, lHdr.getValue());
+ }
+ }
+ }
+
+ private void flushEntry(final String uri) {
+ try {
+ storage.removeEntry(uri);
+ } catch (final IOException ioe) {
+ log.warn("unable to flush cache entry", ioe);
+ }
+ }
+
+ private HttpCacheEntry getEntry(final String theUri) {
+ try {
+ return storage.getEntry(theUri);
+ } catch (final IOException ioe) {
+ log.warn("could not retrieve entry from storage", ioe);
+ }
+ return null;
+ }
+
+ protected void flushUriIfSameHost(final URL requestURL, final URL targetURL) {
+ final URL canonicalTarget = getAbsoluteURL(cacheKeyGenerator.canonicalizeUri(targetURL.toString()));
+ if (canonicalTarget == null) {
+ return;
+ }
+ if (canonicalTarget.getAuthority().equalsIgnoreCase(requestURL.getAuthority())) {
+ flushEntry(canonicalTarget.toString());
+ }
+ }
+
+ protected void flushRelativeUriFromSameHost(final URL reqURL, final String relUri) {
+ final URL relURL = getRelativeURL(reqURL, relUri);
+ if (relURL == null) {
+ return;
+ }
+ flushUriIfSameHost(reqURL, relURL);
+ }
+
+
+ protected boolean flushAbsoluteUriFromSameHost(final URL reqURL, final String uri) {
+ final URL absURL = getAbsoluteURL(uri);
+ if (absURL == null) {
+ return false;
+ }
+ flushUriIfSameHost(reqURL,absURL);
+ return true;
+ }
+
+ private URL getAbsoluteURL(final String uri) {
+ URL absURL = null;
+ try {
+ absURL = new URL(uri);
+ } catch (final MalformedURLException mue) {
+ // nop
+ }
+ return absURL;
+ }
+
+ private URL getRelativeURL(final URL reqURL, final String relUri) {
+ URL relURL = null;
+ try {
+ relURL = new URL(reqURL,relUri);
+ } catch (final MalformedURLException e) {
+ // nop
+ }
+ return relURL;
+ }
+
+ protected boolean requestShouldNotBeCached(final HttpRequest req) {
+ final String method = req.getRequestLine().getMethod();
+ return notGetOrHeadRequest(method);
+ }
+
+ private boolean notGetOrHeadRequest(final String method) {
+ return !(HeaderConstants.GET_METHOD.equals(method) || HeaderConstants.HEAD_METHOD
+ .equals(method));
+ }
+
+ /** Flushes entries that were invalidated by the given response
+ * received for the given host/request pair.
+ */
+ public void flushInvalidatedCacheEntries(final HttpHost host,
+ final HttpRequest request, final HttpResponse response) {
+ final int status = response.getStatusLine().getStatusCode();
+ if (status < 200 || status > 299) {
+ return;
+ }
+ final URL reqURL = getAbsoluteURL(cacheKeyGenerator.getURI(host, request));
+ if (reqURL == null) {
+ return;
+ }
+ final URL contentLocation = getContentLocationURL(reqURL, response);
+ if (contentLocation != null) {
+ flushLocationCacheEntry(reqURL, response, contentLocation);
+ }
+ final URL location = getLocationURL(reqURL, response);
+ if (location != null) {
+ flushLocationCacheEntry(reqURL, response, location);
+ }
+ }
+
+ private void flushLocationCacheEntry(final URL reqURL,
+ final HttpResponse response, final URL location) {
+ final String cacheKey = cacheKeyGenerator.canonicalizeUri(location.toString());
+ final HttpCacheEntry entry = getEntry(cacheKey);
+ if (entry == null) {
+ return;
+ }
+
+ // do not invalidate if response is strictly older than entry
+ // or if the etags match
+
+ if (responseDateOlderThanEntryDate(response, entry)) {
+ return;
+ }
+ if (!responseAndEntryEtagsDiffer(response, entry)) {
+ return;
+ }
+
+ flushUriIfSameHost(reqURL, location);
+ }
+
+ private URL getContentLocationURL(final URL reqURL, final HttpResponse response) {
+ final Header clHeader = response.getFirstHeader("Content-Location");
+ if (clHeader == null) {
+ return null;
+ }
+ final String contentLocation = clHeader.getValue();
+ final URL canonURL = getAbsoluteURL(contentLocation);
+ if (canonURL != null) {
+ return canonURL;
+ }
+ return getRelativeURL(reqURL, contentLocation);
+ }
+
+ private URL getLocationURL(final URL reqURL, final HttpResponse response) {
+ final Header clHeader = response.getFirstHeader("Location");
+ if (clHeader == null) {
+ return null;
+ }
+ final String location = clHeader.getValue();
+ final URL canonURL = getAbsoluteURL(location);
+ if (canonURL != null) {
+ return canonURL;
+ }
+ return getRelativeURL(reqURL, location);
+ }
+
+ private boolean responseAndEntryEtagsDiffer(final HttpResponse response,
+ final HttpCacheEntry entry) {
+ final Header entryEtag = entry.getFirstHeader(HeaderConstants.ETAG);
+ final Header responseEtag = response.getFirstHeader(HeaderConstants.ETAG);
+ if (entryEtag == null || responseEtag == null) {
+ return false;
+ }
+ return (!entryEtag.getValue().equals(responseEtag.getValue()));
+ }
+
+ private boolean responseDateOlderThanEntryDate(final HttpResponse response,
+ final HttpCacheEntry entry) {
+ final Header entryDateHeader = entry.getFirstHeader(HTTP.DATE_HEADER);
+ final Header responseDateHeader = response.getFirstHeader(HTTP.DATE_HEADER);
+ if (entryDateHeader == null || responseDateHeader == null) {
+ /* be conservative; should probably flush */
+ return false;
+ }
+ final Date entryDate = DateUtils.parseDate(entryDateHeader.getValue());
+ final Date responseDate = DateUtils.parseDate(responseDateHeader.getValue());
+ if (entryDate == null || responseDate == null) {
+ return false;
+ }
+ return responseDate.before(entryDate);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheKeyGenerator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheKeyGenerator.java
new file mode 100644
index 000000000..b0628041f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheKeyGenerator.java
@@ -0,0 +1,178 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+
+/**
+ * @since 4.1
+ */
+@Immutable
+class CacheKeyGenerator {
+
+ private static final URI BASE_URI = URI.create("http://example.com/");
+
+ /**
+ * For a given {@link HttpHost} and {@link HttpRequest} get a URI from the
+ * pair that I can use as an identifier KEY into my HttpCache
+ *
+ * @param host The host for this request
+ * @param req the {@link HttpRequest}
+ * @return String the extracted URI
+ */
+ public String getURI(final HttpHost host, final HttpRequest req) {
+ if (isRelativeRequest(req)) {
+ return canonicalizeUri(String.format("%s%s", host.toString(), req.getRequestLine().getUri()));
+ }
+ return canonicalizeUri(req.getRequestLine().getUri());
+ }
+
+ public String canonicalizeUri(final String uri) {
+ try {
+ final URI normalized = URIUtils.resolve(BASE_URI, uri);
+ final URL u = new URL(normalized.toASCIIString());
+ final String protocol = u.getProtocol();
+ final String hostname = u.getHost();
+ final int port = canonicalizePort(u.getPort(), protocol);
+ final String path = u.getPath();
+ final String query = u.getQuery();
+ final String file = (query != null) ? (path + "?" + query) : path;
+ final URL out = new URL(protocol, hostname, port, file);
+ return out.toString();
+ } catch (final IllegalArgumentException e) {
+ return uri;
+ } catch (final MalformedURLException e) {
+ return uri;
+ }
+ }
+
+ private int canonicalizePort(final int port, final String protocol) {
+ if (port == -1 && "http".equalsIgnoreCase(protocol)) {
+ return 80;
+ } else if (port == -1 && "https".equalsIgnoreCase(protocol)) {
+ return 443;
+ }
+ return port;
+ }
+
+ private boolean isRelativeRequest(final HttpRequest req) {
+ final String requestUri = req.getRequestLine().getUri();
+ return ("*".equals(requestUri) || requestUri.startsWith("/"));
+ }
+
+ protected String getFullHeaderValue(final Header[] headers) {
+ if (headers == null) {
+ return "";
+ }
+
+ final StringBuilder buf = new StringBuilder("");
+ boolean first = true;
+ for (final Header hdr : headers) {
+ if (!first) {
+ buf.append(", ");
+ }
+ buf.append(hdr.getValue().trim());
+ first = false;
+
+ }
+ return buf.toString();
+ }
+
+ /**
+ * For a given {@link HttpHost} and {@link HttpRequest} if the request has a
+ * VARY header - I need to get an additional URI from the pair of host and
+ * request so that I can also store the variant into my HttpCache.
+ *
+ * @param host The host for this request
+ * @param req the {@link HttpRequest}
+ * @param entry the parent entry used to track the variants
+ * @return String the extracted variant URI
+ */
+ public String getVariantURI(final HttpHost host, final HttpRequest req, final HttpCacheEntry entry) {
+ if (!entry.hasVariants()) {
+ return getURI(host, req);
+ }
+ return getVariantKey(req, entry) + getURI(host, req);
+ }
+
+ /**
+ * Compute a "variant key" from the headers of a given request that are
+ * covered by the Vary header of a given cache entry. Any request whose
+ * varying headers match those of this request should have the same
+ * variant key.
+ * @param req originating request
+ * @param entry cache entry in question that has variants
+ * @return a <code>String</code> variant key
+ */
+ public String getVariantKey(final HttpRequest req, final HttpCacheEntry entry) {
+ final List<String> variantHeaderNames = new ArrayList<String>();
+ for (final Header varyHdr : entry.getHeaders(HeaderConstants.VARY)) {
+ for (final HeaderElement elt : varyHdr.getElements()) {
+ variantHeaderNames.add(elt.getName());
+ }
+ }
+ Collections.sort(variantHeaderNames);
+
+ StringBuilder buf;
+ try {
+ buf = new StringBuilder("{");
+ boolean first = true;
+ for (final String headerName : variantHeaderNames) {
+ if (!first) {
+ buf.append("&");
+ }
+ buf.append(URLEncoder.encode(headerName, Consts.UTF_8.name()));
+ buf.append("=");
+ buf.append(URLEncoder.encode(getFullHeaderValue(req.getHeaders(headerName)),
+ Consts.UTF_8.name()));
+ first = false;
+ }
+ buf.append("}");
+ } catch (final UnsupportedEncodingException uee) {
+ throw new RuntimeException("couldn't encode to UTF-8", uee);
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheMap.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheMap.java
new file mode 100644
index 000000000..0ed80920c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheMap.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+
+final class CacheMap extends LinkedHashMap<String, HttpCacheEntry> {
+
+ private static final long serialVersionUID = -7750025207539768511L;
+
+ private final int maxEntries;
+
+ CacheMap(final int maxEntries) {
+ super(20, 0.75f, true);
+ this.maxEntries = maxEntries;
+ }
+
+ @Override
+ protected boolean removeEldestEntry(final Map.Entry<String, HttpCacheEntry> eldest) {
+ return size() > this.maxEntries;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheValidityPolicy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheValidityPolicy.java
new file mode 100644
index 000000000..333dfbbfb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheValidityPolicy.java
@@ -0,0 +1,320 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.Date;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * @since 4.1
+ */
+@Immutable
+class CacheValidityPolicy {
+
+ public static final long MAX_AGE = 2147483648L;
+
+ CacheValidityPolicy() {
+ super();
+ }
+
+ public long getCurrentAgeSecs(final HttpCacheEntry entry, final Date now) {
+ return getCorrectedInitialAgeSecs(entry) + getResidentTimeSecs(entry, now);
+ }
+
+ public long getFreshnessLifetimeSecs(final HttpCacheEntry entry) {
+ final long maxage = getMaxAge(entry);
+ if (maxage > -1) {
+ return maxage;
+ }
+
+ final Date dateValue = entry.getDate();
+ if (dateValue == null) {
+ return 0L;
+ }
+
+ final Date expiry = getExpirationDate(entry);
+ if (expiry == null) {
+ return 0;
+ }
+ final long diff = expiry.getTime() - dateValue.getTime();
+ return (diff / 1000);
+ }
+
+ public boolean isResponseFresh(final HttpCacheEntry entry, final Date now) {
+ return (getCurrentAgeSecs(entry, now) < getFreshnessLifetimeSecs(entry));
+ }
+
+ /**
+ * Decides if this response is fresh enough based Last-Modified and Date, if available.
+ * This entry is meant to be used when isResponseFresh returns false. The algorithm is as follows:
+ *
+ * if last-modified and date are defined, freshness lifetime is coefficient*(date-lastModified),
+ * else freshness lifetime is defaultLifetime
+ *
+ * @param entry the cache entry
+ * @param now what time is it currently (When is right NOW)
+ * @param coefficient Part of the heuristic for cache entry freshness
+ * @param defaultLifetime How long can I assume a cache entry is default TTL
+ * @return {@code true} if the response is fresh
+ */
+ public boolean isResponseHeuristicallyFresh(final HttpCacheEntry entry,
+ final Date now, final float coefficient, final long defaultLifetime) {
+ return (getCurrentAgeSecs(entry, now) < getHeuristicFreshnessLifetimeSecs(entry, coefficient, defaultLifetime));
+ }
+
+ public long getHeuristicFreshnessLifetimeSecs(final HttpCacheEntry entry,
+ final float coefficient, final long defaultLifetime) {
+ final Date dateValue = entry.getDate();
+ final Date lastModifiedValue = getLastModifiedValue(entry);
+
+ if (dateValue != null && lastModifiedValue != null) {
+ final long diff = dateValue.getTime() - lastModifiedValue.getTime();
+ if (diff < 0) {
+ return 0;
+ }
+ return (long)(coefficient * (diff / 1000));
+ }
+
+ return defaultLifetime;
+ }
+
+ public boolean isRevalidatable(final HttpCacheEntry entry) {
+ return entry.getFirstHeader(HeaderConstants.ETAG) != null
+ || entry.getFirstHeader(HeaderConstants.LAST_MODIFIED) != null;
+ }
+
+ public boolean mustRevalidate(final HttpCacheEntry entry) {
+ return hasCacheControlDirective(entry, HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE);
+ }
+
+ public boolean proxyRevalidate(final HttpCacheEntry entry) {
+ return hasCacheControlDirective(entry, HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE);
+ }
+
+ public boolean mayReturnStaleWhileRevalidating(final HttpCacheEntry entry, final Date now) {
+ for (final Header h : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) {
+ try {
+ final int allowedStalenessLifetime = Integer.parseInt(elt.getValue());
+ if (getStalenessSecs(entry, now) <= allowedStalenessLifetime) {
+ return true;
+ }
+ } catch (final NumberFormatException nfe) {
+ // skip malformed directive
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public boolean mayReturnStaleIfError(final HttpRequest request,
+ final HttpCacheEntry entry, final Date now) {
+ final long stalenessSecs = getStalenessSecs(entry, now);
+ return mayReturnStaleIfError(request.getHeaders(HeaderConstants.CACHE_CONTROL),
+ stalenessSecs)
+ || mayReturnStaleIfError(entry.getHeaders(HeaderConstants.CACHE_CONTROL),
+ stalenessSecs);
+ }
+
+ private boolean mayReturnStaleIfError(final Header[] headers, final long stalenessSecs) {
+ boolean result = false;
+ for(final Header h : headers) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) {
+ try {
+ final int staleIfErrorSecs = Integer.parseInt(elt.getValue());
+ if (stalenessSecs <= staleIfErrorSecs) {
+ result = true;
+ break;
+ }
+ } catch (final NumberFormatException nfe) {
+ // skip malformed directive
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @deprecated (4.3) use {@link HttpCacheEntry#getDate()}.
+ * @param entry
+ * @return the Date of the entry
+ */
+ @Deprecated
+ protected Date getDateValue(final HttpCacheEntry entry) {
+ return entry.getDate();
+ }
+
+ protected Date getLastModifiedValue(final HttpCacheEntry entry) {
+ final Header dateHdr = entry.getFirstHeader(HeaderConstants.LAST_MODIFIED);
+ if (dateHdr == null) {
+ return null;
+ }
+ return DateUtils.parseDate(dateHdr.getValue());
+ }
+
+ protected long getContentLengthValue(final HttpCacheEntry entry) {
+ final Header cl = entry.getFirstHeader(HTTP.CONTENT_LEN);
+ if (cl == null) {
+ return -1;
+ }
+
+ try {
+ return Long.parseLong(cl.getValue());
+ } catch (final NumberFormatException ex) {
+ return -1;
+ }
+ }
+
+ protected boolean hasContentLengthHeader(final HttpCacheEntry entry) {
+ return null != entry.getFirstHeader(HTTP.CONTENT_LEN);
+ }
+
+ /**
+ * This matters for deciding whether the cache entry is valid to serve as a
+ * response. If these values do not match, we might have a partial response
+ *
+ * @param entry The cache entry we are currently working with
+ * @return boolean indicating whether actual length matches Content-Length
+ */
+ protected boolean contentLengthHeaderMatchesActualLength(final HttpCacheEntry entry) {
+ return !hasContentLengthHeader(entry) || getContentLengthValue(entry) == entry.getResource().length();
+ }
+
+ protected long getApparentAgeSecs(final HttpCacheEntry entry) {
+ final Date dateValue = entry.getDate();
+ if (dateValue == null) {
+ return MAX_AGE;
+ }
+ final long diff = entry.getResponseDate().getTime() - dateValue.getTime();
+ if (diff < 0L) {
+ return 0;
+ }
+ return (diff / 1000);
+ }
+
+ protected long getAgeValue(final HttpCacheEntry entry) {
+ long ageValue = 0;
+ for (final Header hdr : entry.getHeaders(HeaderConstants.AGE)) {
+ long hdrAge;
+ try {
+ hdrAge = Long.parseLong(hdr.getValue());
+ if (hdrAge < 0) {
+ hdrAge = MAX_AGE;
+ }
+ } catch (final NumberFormatException nfe) {
+ hdrAge = MAX_AGE;
+ }
+ ageValue = (hdrAge > ageValue) ? hdrAge : ageValue;
+ }
+ return ageValue;
+ }
+
+ protected long getCorrectedReceivedAgeSecs(final HttpCacheEntry entry) {
+ final long apparentAge = getApparentAgeSecs(entry);
+ final long ageValue = getAgeValue(entry);
+ return (apparentAge > ageValue) ? apparentAge : ageValue;
+ }
+
+ protected long getResponseDelaySecs(final HttpCacheEntry entry) {
+ final long diff = entry.getResponseDate().getTime() - entry.getRequestDate().getTime();
+ return (diff / 1000L);
+ }
+
+ protected long getCorrectedInitialAgeSecs(final HttpCacheEntry entry) {
+ return getCorrectedReceivedAgeSecs(entry) + getResponseDelaySecs(entry);
+ }
+
+ protected long getResidentTimeSecs(final HttpCacheEntry entry, final Date now) {
+ final long diff = now.getTime() - entry.getResponseDate().getTime();
+ return (diff / 1000L);
+ }
+
+ protected long getMaxAge(final HttpCacheEntry entry) {
+ long maxage = -1;
+ for (final Header hdr : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for (final HeaderElement elt : hdr.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())
+ || "s-maxage".equals(elt.getName())) {
+ try {
+ final long currMaxAge = Long.parseLong(elt.getValue());
+ if (maxage == -1 || currMaxAge < maxage) {
+ maxage = currMaxAge;
+ }
+ } catch (final NumberFormatException nfe) {
+ // be conservative if can't parse
+ maxage = 0;
+ }
+ }
+ }
+ }
+ return maxage;
+ }
+
+ protected Date getExpirationDate(final HttpCacheEntry entry) {
+ final Header expiresHeader = entry.getFirstHeader(HeaderConstants.EXPIRES);
+ if (expiresHeader == null) {
+ return null;
+ }
+ return DateUtils.parseDate(expiresHeader.getValue());
+ }
+
+ public boolean hasCacheControlDirective(final HttpCacheEntry entry,
+ final String directive) {
+ for (final Header h : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (directive.equalsIgnoreCase(elt.getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public long getStalenessSecs(final HttpCacheEntry entry, final Date now) {
+ final long age = getCurrentAgeSecs(entry, now);
+ final long freshness = getFreshnessLifetimeSecs(entry);
+ if (age <= freshness) {
+ return 0L;
+ }
+ return (age - freshness);
+ }
+
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheableRequestPolicy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheableRequestPolicy.java
new file mode 100644
index 000000000..500da01dc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CacheableRequestPolicy.java
@@ -0,0 +1,96 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+
+/**
+ * Determines if an HttpRequest is allowed to be served from the cache.
+ *
+ * @since 4.1
+ */
+@Immutable
+class CacheableRequestPolicy {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /**
+ * Determines if an HttpRequest can be served from the cache.
+ *
+ * @param request
+ * an HttpRequest
+ * @return boolean Is it possible to serve this request from cache
+ */
+ public boolean isServableFromCache(final HttpRequest request) {
+ final String method = request.getRequestLine().getMethod();
+
+ final ProtocolVersion pv = request.getRequestLine().getProtocolVersion();
+ if (HttpVersion.HTTP_1_1.compareToVersion(pv) != 0) {
+ log.trace("non-HTTP/1.1 request was not serveable from cache");
+ return false;
+ }
+
+ if (!method.equals(HeaderConstants.GET_METHOD)) {
+ log.trace("non-GET request was not serveable from cache");
+ return false;
+ }
+
+ if (request.getHeaders(HeaderConstants.PRAGMA).length > 0) {
+ log.trace("request with Pragma header was not serveable from cache");
+ return false;
+ }
+
+ final Header[] cacheControlHeaders = request.getHeaders(HeaderConstants.CACHE_CONTROL);
+ for (final Header cacheControl : cacheControlHeaders) {
+ for (final HeaderElement cacheControlElement : cacheControl.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_NO_STORE.equalsIgnoreCase(cacheControlElement
+ .getName())) {
+ log.trace("Request with no-store was not serveable from cache");
+ return false;
+ }
+
+ if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(cacheControlElement
+ .getName())) {
+ log.trace("Request with no-cache was not serveable from cache");
+ return false;
+ }
+ }
+ }
+
+ log.trace("Request was serveable from cache");
+ return true;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedHttpResponseGenerator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedHttpResponseGenerator.java
new file mode 100644
index 000000000..f42529e57
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedHttpResponseGenerator.java
@@ -0,0 +1,166 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.Date;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * Rebuilds an {@link HttpResponse} from a {@link net.sf.ehcache.CacheEntry}
+ *
+ * @since 4.1
+ */
+@Immutable
+class CachedHttpResponseGenerator {
+
+ private final CacheValidityPolicy validityStrategy;
+
+ CachedHttpResponseGenerator(final CacheValidityPolicy validityStrategy) {
+ super();
+ this.validityStrategy = validityStrategy;
+ }
+
+ CachedHttpResponseGenerator() {
+ this(new CacheValidityPolicy());
+ }
+
+ /**
+ * If I was able to use a {@link CacheEntity} to response to the {@link ch.boye.httpclientandroidlib.HttpRequest} then
+ * generate an {@link HttpResponse} based on the cache entry.
+ * @param entry
+ * {@link CacheEntity} to transform into an {@link HttpResponse}
+ * @return {@link HttpResponse} that was constructed
+ */
+ CloseableHttpResponse generateResponse(final HttpCacheEntry entry) {
+
+ final Date now = new Date();
+ final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, entry
+ .getStatusCode(), entry.getReasonPhrase());
+
+ response.setHeaders(entry.getAllHeaders());
+
+ if (entry.getResource() != null) {
+ final HttpEntity entity = new CacheEntity(entry);
+ addMissingContentLengthHeader(response, entity);
+ response.setEntity(entity);
+ }
+
+ final long age = this.validityStrategy.getCurrentAgeSecs(entry, now);
+ if (age > 0) {
+ if (age >= Integer.MAX_VALUE) {
+ response.setHeader(HeaderConstants.AGE, "2147483648");
+ } else {
+ response.setHeader(HeaderConstants.AGE, "" + ((int) age));
+ }
+ }
+
+ return Proxies.enhanceResponse(response);
+ }
+
+ /**
+ * Generate a 304 - Not Modified response from a {@link CacheEntity}. This should be
+ * used to respond to conditional requests, when the entry exists or has been re-validated.
+ */
+ CloseableHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
+
+ final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_NOT_MODIFIED, "Not Modified");
+
+ // The response MUST include the following headers
+ // (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
+
+ // - Date, unless its omission is required by section 14.8.1
+ Header dateHeader = entry.getFirstHeader(HTTP.DATE_HEADER);
+ if (dateHeader == null) {
+ dateHeader = new BasicHeader(HTTP.DATE_HEADER, DateUtils.formatDate(new Date()));
+ }
+ response.addHeader(dateHeader);
+
+ // - ETag and/or Content-Location, if the header would have been sent
+ // in a 200 response to the same request
+ final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
+ if (etagHeader != null) {
+ response.addHeader(etagHeader);
+ }
+
+ final Header contentLocationHeader = entry.getFirstHeader("Content-Location");
+ if (contentLocationHeader != null) {
+ response.addHeader(contentLocationHeader);
+ }
+
+ // - Expires, Cache-Control, and/or Vary, if the field-value might
+ // differ from that sent in any previous response for the same
+ // variant
+ final Header expiresHeader = entry.getFirstHeader(HeaderConstants.EXPIRES);
+ if (expiresHeader != null) {
+ response.addHeader(expiresHeader);
+ }
+
+ final Header cacheControlHeader = entry.getFirstHeader(HeaderConstants.CACHE_CONTROL);
+ if (cacheControlHeader != null) {
+ response.addHeader(cacheControlHeader);
+ }
+
+ final Header varyHeader = entry.getFirstHeader(HeaderConstants.VARY);
+ if (varyHeader != null) {
+ response.addHeader(varyHeader);
+ }
+
+ return Proxies.enhanceResponse(response);
+ }
+
+ private void addMissingContentLengthHeader(final HttpResponse response, final HttpEntity entity) {
+ if (transferEncodingIsPresent(response)) {
+ return;
+ }
+
+ Header contentLength = response.getFirstHeader(HTTP.CONTENT_LEN);
+ if (contentLength == null) {
+ contentLength = new BasicHeader(HTTP.CONTENT_LEN, Long.toString(entity
+ .getContentLength()));
+ response.setHeader(contentLength);
+ }
+ }
+
+ private boolean transferEncodingIsPresent(final HttpResponse response) {
+ final Header hdr = response.getFirstHeader(HTTP.TRANSFER_ENCODING);
+ return hdr != null;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedResponseSuitabilityChecker.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedResponseSuitabilityChecker.java
new file mode 100644
index 000000000..a289729d3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachedResponseSuitabilityChecker.java
@@ -0,0 +1,346 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.Date;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+
+/**
+ * Determines whether a given {@link HttpCacheEntry} is suitable to be
+ * used as a response for a given {@link HttpRequest}.
+ *
+ * @since 4.1
+ */
+@Immutable
+class CachedResponseSuitabilityChecker {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final boolean sharedCache;
+ private final boolean useHeuristicCaching;
+ private final float heuristicCoefficient;
+ private final long heuristicDefaultLifetime;
+ private final CacheValidityPolicy validityStrategy;
+
+ CachedResponseSuitabilityChecker(final CacheValidityPolicy validityStrategy,
+ final CacheConfig config) {
+ super();
+ this.validityStrategy = validityStrategy;
+ this.sharedCache = config.isSharedCache();
+ this.useHeuristicCaching = config.isHeuristicCachingEnabled();
+ this.heuristicCoefficient = config.getHeuristicCoefficient();
+ this.heuristicDefaultLifetime = config.getHeuristicDefaultLifetime();
+ }
+
+ CachedResponseSuitabilityChecker(final CacheConfig config) {
+ this(new CacheValidityPolicy(), config);
+ }
+
+ private boolean isFreshEnough(final HttpCacheEntry entry, final HttpRequest request, final Date now) {
+ if (validityStrategy.isResponseFresh(entry, now)) {
+ return true;
+ }
+ if (useHeuristicCaching &&
+ validityStrategy.isResponseHeuristicallyFresh(entry, now, heuristicCoefficient, heuristicDefaultLifetime)) {
+ return true;
+ }
+ if (originInsistsOnFreshness(entry)) {
+ return false;
+ }
+ final long maxstale = getMaxStale(request);
+ if (maxstale == -1) {
+ return false;
+ }
+ return (maxstale > validityStrategy.getStalenessSecs(entry, now));
+ }
+
+ private boolean originInsistsOnFreshness(final HttpCacheEntry entry) {
+ if (validityStrategy.mustRevalidate(entry)) {
+ return true;
+ }
+ if (!sharedCache) {
+ return false;
+ }
+ return validityStrategy.proxyRevalidate(entry) ||
+ validityStrategy.hasCacheControlDirective(entry, "s-maxage");
+ }
+
+ private long getMaxStale(final HttpRequest request) {
+ long maxstale = -1;
+ for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
+ if ((elt.getValue() == null || "".equals(elt.getValue().trim()))
+ && maxstale == -1) {
+ maxstale = Long.MAX_VALUE;
+ } else {
+ try {
+ long val = Long.parseLong(elt.getValue());
+ if (val < 0) {
+ val = 0;
+ }
+ if (maxstale == -1 || val < maxstale) {
+ maxstale = val;
+ }
+ } catch (final NumberFormatException nfe) {
+ // err on the side of preserving semantic transparency
+ maxstale = 0;
+ }
+ }
+ }
+ }
+ }
+ return maxstale;
+ }
+
+ /**
+ * Determine if I can utilize a {@link HttpCacheEntry} to respond to the given
+ * {@link HttpRequest}
+ *
+ * @param host
+ * {@link HttpHost}
+ * @param request
+ * {@link HttpRequest}
+ * @param entry
+ * {@link HttpCacheEntry}
+ * @param now
+ * Right now in time
+ * @return boolean yes/no answer
+ */
+ public boolean canCachedResponseBeUsed(final HttpHost host, final HttpRequest request, final HttpCacheEntry entry, final Date now) {
+
+ if (!isFreshEnough(entry, request, now)) {
+ log.trace("Cache entry was not fresh enough");
+ return false;
+ }
+
+ if (!validityStrategy.contentLengthHeaderMatchesActualLength(entry)) {
+ log.debug("Cache entry Content-Length and header information do not match");
+ return false;
+ }
+
+ if (hasUnsupportedConditionalHeaders(request)) {
+ log.debug("Request contained conditional headers we don't handle");
+ return false;
+ }
+
+ if (!isConditional(request) && entry.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+ return false;
+ }
+
+ if (isConditional(request) && !allConditionalsMatch(request, entry, now)) {
+ return false;
+ }
+
+ for (final Header ccHdr : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for (final HeaderElement elt : ccHdr.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
+ log.trace("Response contained NO CACHE directive, cache was not suitable");
+ return false;
+ }
+
+ if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elt.getName())) {
+ log.trace("Response contained NO STORE directive, cache was not suitable");
+ return false;
+ }
+
+ if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
+ try {
+ final int maxage = Integer.parseInt(elt.getValue());
+ if (validityStrategy.getCurrentAgeSecs(entry, now) > maxage) {
+ log.trace("Response from cache was NOT suitable due to max age");
+ return false;
+ }
+ } catch (final NumberFormatException ex) {
+ // err conservatively
+ log.debug("Response from cache was malformed" + ex.getMessage());
+ return false;
+ }
+ }
+
+ if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
+ try {
+ final int maxstale = Integer.parseInt(elt.getValue());
+ if (validityStrategy.getFreshnessLifetimeSecs(entry) > maxstale) {
+ log.trace("Response from cache was not suitable due to Max stale freshness");
+ return false;
+ }
+ } catch (final NumberFormatException ex) {
+ // err conservatively
+ log.debug("Response from cache was malformed: " + ex.getMessage());
+ return false;
+ }
+ }
+
+ if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
+ try {
+ final long minfresh = Long.parseLong(elt.getValue());
+ if (minfresh < 0L) {
+ return false;
+ }
+ final long age = validityStrategy.getCurrentAgeSecs(entry, now);
+ final long freshness = validityStrategy.getFreshnessLifetimeSecs(entry);
+ if (freshness - age < minfresh) {
+ log.trace("Response from cache was not suitable due to min fresh " +
+ "freshness requirement");
+ return false;
+ }
+ } catch (final NumberFormatException ex) {
+ // err conservatively
+ log.debug("Response from cache was malformed: " + ex.getMessage());
+ return false;
+ }
+ }
+ }
+ }
+
+ log.trace("Response from cache was suitable");
+ return true;
+ }
+
+ /**
+ * Is this request the type of conditional request we support?
+ * @param request The current httpRequest being made
+ * @return {@code true} if the request is supported
+ */
+ public boolean isConditional(final HttpRequest request) {
+ return hasSupportedEtagValidator(request) || hasSupportedLastModifiedValidator(request);
+ }
+
+ /**
+ * Check that conditionals that are part of this request match
+ * @param request The current httpRequest being made
+ * @param entry the cache entry
+ * @param now right NOW in time
+ * @return {@code true} if the request matches all conditionals
+ */
+ public boolean allConditionalsMatch(final HttpRequest request, final HttpCacheEntry entry, final Date now) {
+ final boolean hasEtagValidator = hasSupportedEtagValidator(request);
+ final boolean hasLastModifiedValidator = hasSupportedLastModifiedValidator(request);
+
+ final boolean etagValidatorMatches = (hasEtagValidator) && etagValidatorMatches(request, entry);
+ final boolean lastModifiedValidatorMatches = (hasLastModifiedValidator) && lastModifiedValidatorMatches(request, entry, now);
+
+ if ((hasEtagValidator && hasLastModifiedValidator)
+ && !(etagValidatorMatches && lastModifiedValidatorMatches)) {
+ return false;
+ } else if (hasEtagValidator && !etagValidatorMatches) {
+ return false;
+ }
+
+ if (hasLastModifiedValidator && !lastModifiedValidatorMatches) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean hasUnsupportedConditionalHeaders(final HttpRequest request) {
+ return (request.getFirstHeader(HeaderConstants.IF_RANGE) != null
+ || request.getFirstHeader(HeaderConstants.IF_MATCH) != null
+ || hasValidDateField(request, HeaderConstants.IF_UNMODIFIED_SINCE));
+ }
+
+ private boolean hasSupportedEtagValidator(final HttpRequest request) {
+ return request.containsHeader(HeaderConstants.IF_NONE_MATCH);
+ }
+
+ private boolean hasSupportedLastModifiedValidator(final HttpRequest request) {
+ return hasValidDateField(request, HeaderConstants.IF_MODIFIED_SINCE);
+ }
+
+ /**
+ * Check entry against If-None-Match
+ * @param request The current httpRequest being made
+ * @param entry the cache entry
+ * @return boolean does the etag validator match
+ */
+ private boolean etagValidatorMatches(final HttpRequest request, final HttpCacheEntry entry) {
+ final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
+ final String etag = (etagHeader != null) ? etagHeader.getValue() : null;
+ final Header[] ifNoneMatch = request.getHeaders(HeaderConstants.IF_NONE_MATCH);
+ if (ifNoneMatch != null) {
+ for (final Header h : ifNoneMatch) {
+ for (final HeaderElement elt : h.getElements()) {
+ final String reqEtag = elt.toString();
+ if (("*".equals(reqEtag) && etag != null)
+ || reqEtag.equals(etag)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check entry against If-Modified-Since, if If-Modified-Since is in the future it is invalid as per
+ * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+ * @param request The current httpRequest being made
+ * @param entry the cache entry
+ * @param now right NOW in time
+ * @return boolean Does the last modified header match
+ */
+ private boolean lastModifiedValidatorMatches(final HttpRequest request, final HttpCacheEntry entry, final Date now) {
+ final Header lastModifiedHeader = entry.getFirstHeader(HeaderConstants.LAST_MODIFIED);
+ Date lastModified = null;
+ if (lastModifiedHeader != null) {
+ lastModified = DateUtils.parseDate(lastModifiedHeader.getValue());
+ }
+ if (lastModified == null) {
+ return false;
+ }
+
+ for (final Header h : request.getHeaders(HeaderConstants.IF_MODIFIED_SINCE)) {
+ final Date ifModifiedSince = DateUtils.parseDate(h.getValue());
+ if (ifModifiedSince != null) {
+ if (ifModifiedSince.after(now) || lastModified.after(ifModifiedSince)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean hasValidDateField(final HttpRequest request, final String headerName) {
+ for(final Header h : request.getHeaders(headerName)) {
+ final Date date = DateUtils.parseDate(h.getValue());
+ return date != null;
+ }
+ return false;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingExec.java
new file mode 100644
index 000000000..cf9b8154a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingExec.java
@@ -0,0 +1,870 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.cache.CacheResponseStatus;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheContext;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage;
+import ch.boye.httpclientandroidlib.client.cache.ResourceFactory;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.impl.execchain.ClientExecChain;
+import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.VersionInfo;
+
+/**
+ * Request executor in the request execution chain that is responsible for
+ * transparent client-side caching. The current implementation is conditionally
+ * compliant with HTTP/1.1 (meaning all the MUST and MUST NOTs are obeyed),
+ * although quite a lot, though not all, of the SHOULDs and SHOULD NOTs
+ * are obeyed too.
+ * <p/>
+ * Folks that would like to experiment with alternative storage backends
+ * should look at the {@link HttpCacheStorage} interface and the related
+ * package documentation there. You may also be interested in the provided
+ * {@link ch.boye.httpclientandroidlib.impl.client.cache.ehcache.EhcacheHttpCacheStorage
+ * EhCache} and {@link
+ * ch.boye.httpclientandroidlib.impl.client.cache.memcached.MemcachedHttpCacheStorage
+ * memcached} storage backends.
+ * <p/>
+ * Further responsibilities such as communication with the opposite
+ * endpoint is delegated to the next executor in the request execution
+ * chain.
+ *
+ * @since 4.3
+ */
+@ThreadSafe // So long as the responseCache implementation is threadsafe
+public class CachingExec implements ClientExecChain {
+
+ private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false;
+
+ private final AtomicLong cacheHits = new AtomicLong();
+ private final AtomicLong cacheMisses = new AtomicLong();
+ private final AtomicLong cacheUpdates = new AtomicLong();
+
+ private final Map<ProtocolVersion, String> viaHeaders = new HashMap<ProtocolVersion, String>(4);
+
+ private final CacheConfig cacheConfig;
+ private final ClientExecChain backend;
+ private final HttpCache responseCache;
+ private final CacheValidityPolicy validityPolicy;
+ private final CachedHttpResponseGenerator responseGenerator;
+ private final CacheableRequestPolicy cacheableRequestPolicy;
+ private final CachedResponseSuitabilityChecker suitabilityChecker;
+ private final ConditionalRequestBuilder conditionalRequestBuilder;
+ private final ResponseProtocolCompliance responseCompliance;
+ private final RequestProtocolCompliance requestCompliance;
+ private final ResponseCachingPolicy responseCachingPolicy;
+
+ private final AsynchronousValidator asynchRevalidator;
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ public CachingExec(
+ final ClientExecChain backend,
+ final HttpCache cache,
+ final CacheConfig config) {
+ this(backend, cache, config, null);
+ }
+
+ public CachingExec(
+ final ClientExecChain backend,
+ final HttpCache cache,
+ final CacheConfig config,
+ final AsynchronousValidator asynchRevalidator) {
+ super();
+ Args.notNull(backend, "HTTP backend");
+ Args.notNull(cache, "HttpCache");
+ this.cacheConfig = config != null ? config : CacheConfig.DEFAULT;
+ this.backend = backend;
+ this.responseCache = cache;
+ this.validityPolicy = new CacheValidityPolicy();
+ this.responseGenerator = new CachedHttpResponseGenerator(this.validityPolicy);
+ this.cacheableRequestPolicy = new CacheableRequestPolicy();
+ this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy, this.cacheConfig);
+ this.conditionalRequestBuilder = new ConditionalRequestBuilder();
+ this.responseCompliance = new ResponseProtocolCompliance();
+ this.requestCompliance = new RequestProtocolCompliance(this.cacheConfig.isWeakETagOnPutDeleteAllowed());
+ this.responseCachingPolicy = new ResponseCachingPolicy(
+ this.cacheConfig.getMaxObjectSize(), this.cacheConfig.isSharedCache(),
+ this.cacheConfig.isNeverCacheHTTP10ResponsesWithQuery(), this.cacheConfig.is303CachingEnabled());
+ this.asynchRevalidator = asynchRevalidator;
+ }
+
+ public CachingExec(
+ final ClientExecChain backend,
+ final ResourceFactory resourceFactory,
+ final HttpCacheStorage storage,
+ final CacheConfig config) {
+ this(backend, new BasicHttpCache(resourceFactory, storage, config), config);
+ }
+
+ public CachingExec(final ClientExecChain backend) {
+ this(backend, new BasicHttpCache(), CacheConfig.DEFAULT);
+ }
+
+ CachingExec(
+ final ClientExecChain backend,
+ final HttpCache responseCache,
+ final CacheValidityPolicy validityPolicy,
+ final ResponseCachingPolicy responseCachingPolicy,
+ final CachedHttpResponseGenerator responseGenerator,
+ final CacheableRequestPolicy cacheableRequestPolicy,
+ final CachedResponseSuitabilityChecker suitabilityChecker,
+ final ConditionalRequestBuilder conditionalRequestBuilder,
+ final ResponseProtocolCompliance responseCompliance,
+ final RequestProtocolCompliance requestCompliance,
+ final CacheConfig config,
+ final AsynchronousValidator asynchRevalidator) {
+ this.cacheConfig = config != null ? config : CacheConfig.DEFAULT;
+ this.backend = backend;
+ this.responseCache = responseCache;
+ this.validityPolicy = validityPolicy;
+ this.responseCachingPolicy = responseCachingPolicy;
+ this.responseGenerator = responseGenerator;
+ this.cacheableRequestPolicy = cacheableRequestPolicy;
+ this.suitabilityChecker = suitabilityChecker;
+ this.conditionalRequestBuilder = conditionalRequestBuilder;
+ this.responseCompliance = responseCompliance;
+ this.requestCompliance = requestCompliance;
+ this.asynchRevalidator = asynchRevalidator;
+ }
+
+ /**
+ * Reports the number of times that the cache successfully responded
+ * to an {@link HttpRequest} without contacting the origin server.
+ * @return the number of cache hits
+ */
+ public long getCacheHits() {
+ return cacheHits.get();
+ }
+
+ /**
+ * Reports the number of times that the cache contacted the origin
+ * server because it had no appropriate response cached.
+ * @return the number of cache misses
+ */
+ public long getCacheMisses() {
+ return cacheMisses.get();
+ }
+
+ /**
+ * Reports the number of times that the cache was able to satisfy
+ * a response by revalidating an existing but stale cache entry.
+ * @return the number of cache revalidations
+ */
+ public long getCacheUpdates() {
+ return cacheUpdates.get();
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request) throws IOException, HttpException {
+ return execute(route, request, HttpClientContext.create(), null);
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context) throws IOException, HttpException {
+ return execute(route, request, context, null);
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+
+ final HttpHost target = context.getTargetHost();
+ final String via = generateViaHeader(request.getOriginal());
+
+ // default response context
+ setResponseStatus(context, CacheResponseStatus.CACHE_MISS);
+
+ if (clientRequestsOurOptions(request)) {
+ setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
+ return Proxies.enhanceResponse(new OptionsHttp11Response());
+ }
+
+ final HttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(request, context);
+ if (fatalErrorResponse != null) {
+ return Proxies.enhanceResponse(fatalErrorResponse);
+ }
+
+ requestCompliance.makeRequestCompliant(request);
+ request.addHeader("Via",via);
+
+ flushEntriesInvalidatedByRequest(context.getTargetHost(), request);
+
+ if (!cacheableRequestPolicy.isServableFromCache(request)) {
+ log.debug("Request is not servable from cache");
+ return callBackend(route, request, context, execAware);
+ }
+
+ final HttpCacheEntry entry = satisfyFromCache(target, request);
+ if (entry == null) {
+ log.debug("Cache miss");
+ return handleCacheMiss(route, request, context, execAware);
+ } else {
+ return handleCacheHit(route, request, context, execAware, entry);
+ }
+ }
+
+ private CloseableHttpResponse handleCacheHit(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final HttpCacheEntry entry) throws IOException, HttpException {
+ final HttpHost target = context.getTargetHost();
+ recordCacheHit(target, request);
+ CloseableHttpResponse out = null;
+ final Date now = getCurrentDate();
+ if (suitabilityChecker.canCachedResponseBeUsed(target, request, entry, now)) {
+ log.debug("Cache hit");
+ out = generateCachedResponse(request, context, entry, now);
+ } else if (!mayCallBackend(request)) {
+ log.debug("Cache entry not suitable but only-if-cached requested");
+ out = generateGatewayTimeout(context);
+ } else if (!(entry.getStatusCode() == HttpStatus.SC_NOT_MODIFIED
+ && !suitabilityChecker.isConditional(request))) {
+ log.debug("Revalidating cache entry");
+ return revalidateCacheEntry(route, request, context, execAware, entry, now);
+ } else {
+ log.debug("Cache entry not usable; calling backend");
+ return callBackend(route, request, context, execAware);
+ }
+ context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
+ context.setAttribute(HttpClientContext.HTTP_TARGET_HOST, target);
+ context.setAttribute(HttpClientContext.HTTP_REQUEST, request);
+ context.setAttribute(HttpClientContext.HTTP_RESPONSE, out);
+ context.setAttribute(HttpClientContext.HTTP_REQ_SENT, Boolean.TRUE);
+ return out;
+ }
+
+ private CloseableHttpResponse revalidateCacheEntry(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final HttpCacheEntry entry,
+ final Date now) throws HttpException {
+
+ try {
+ if (asynchRevalidator != null
+ && !staleResponseNotAllowed(request, entry, now)
+ && validityPolicy.mayReturnStaleWhileRevalidating(entry, now)) {
+ log.trace("Serving stale with asynchronous revalidation");
+ final CloseableHttpResponse resp = generateCachedResponse(request, context, entry, now);
+ asynchRevalidator.revalidateCacheEntry(this, route, request, context, execAware, entry);
+ return resp;
+ }
+ return revalidateCacheEntry(route, request, context, execAware, entry);
+ } catch (final IOException ioex) {
+ return handleRevalidationFailure(request, context, entry, now);
+ }
+ }
+
+ private CloseableHttpResponse handleCacheMiss(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+ final HttpHost target = context.getTargetHost();
+ recordCacheMiss(target, request);
+
+ if (!mayCallBackend(request)) {
+ return Proxies.enhanceResponse(
+ new BasicHttpResponse(
+ HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"));
+ }
+
+ final Map<String, Variant> variants = getExistingCacheVariants(target, request);
+ if (variants != null && variants.size() > 0) {
+ return negotiateResponseFromVariants(route, request, context,
+ execAware, variants);
+ }
+
+ return callBackend(route, request, context, execAware);
+ }
+
+ private HttpCacheEntry satisfyFromCache(
+ final HttpHost target, final HttpRequestWrapper request) {
+ HttpCacheEntry entry = null;
+ try {
+ entry = responseCache.getCacheEntry(target, request);
+ } catch (final IOException ioe) {
+ log.warn("Unable to retrieve entries from cache", ioe);
+ }
+ return entry;
+ }
+
+ private HttpResponse getFatallyNoncompliantResponse(
+ final HttpRequestWrapper request,
+ final HttpContext context) {
+ HttpResponse fatalErrorResponse = null;
+ final List<RequestProtocolError> fatalError = requestCompliance.requestIsFatallyNonCompliant(request);
+
+ for (final RequestProtocolError error : fatalError) {
+ setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
+ fatalErrorResponse = requestCompliance.getErrorForRequest(error);
+ }
+ return fatalErrorResponse;
+ }
+
+ private Map<String, Variant> getExistingCacheVariants(
+ final HttpHost target,
+ final HttpRequestWrapper request) {
+ Map<String,Variant> variants = null;
+ try {
+ variants = responseCache.getVariantCacheEntriesWithEtags(target, request);
+ } catch (final IOException ioe) {
+ log.warn("Unable to retrieve variant entries from cache", ioe);
+ }
+ return variants;
+ }
+
+ private void recordCacheMiss(final HttpHost target, final HttpRequestWrapper request) {
+ cacheMisses.getAndIncrement();
+ if (log.isTraceEnabled()) {
+ final RequestLine rl = request.getRequestLine();
+ log.trace("Cache miss [host: " + target + "; uri: " + rl.getUri() + "]");
+ }
+ }
+
+ private void recordCacheHit(final HttpHost target, final HttpRequestWrapper request) {
+ cacheHits.getAndIncrement();
+ if (log.isTraceEnabled()) {
+ final RequestLine rl = request.getRequestLine();
+ log.trace("Cache hit [host: " + target + "; uri: " + rl.getUri() + "]");
+ }
+ }
+
+ private void recordCacheUpdate(final HttpContext context) {
+ cacheUpdates.getAndIncrement();
+ setResponseStatus(context, CacheResponseStatus.VALIDATED);
+ }
+
+ private void flushEntriesInvalidatedByRequest(
+ final HttpHost target,
+ final HttpRequestWrapper request) {
+ try {
+ responseCache.flushInvalidatedCacheEntriesFor(target, request);
+ } catch (final IOException ioe) {
+ log.warn("Unable to flush invalidated entries from cache", ioe);
+ }
+ }
+
+ private CloseableHttpResponse generateCachedResponse(final HttpRequestWrapper request,
+ final HttpContext context, final HttpCacheEntry entry, final Date now) {
+ final CloseableHttpResponse cachedResponse;
+ if (request.containsHeader(HeaderConstants.IF_NONE_MATCH)
+ || request.containsHeader(HeaderConstants.IF_MODIFIED_SINCE)) {
+ cachedResponse = responseGenerator.generateNotModifiedResponse(entry);
+ } else {
+ cachedResponse = responseGenerator.generateResponse(entry);
+ }
+ setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
+ if (validityPolicy.getStalenessSecs(entry, now) > 0L) {
+ cachedResponse.addHeader(HeaderConstants.WARNING,"110 localhost \"Response is stale\"");
+ }
+ return cachedResponse;
+ }
+
+ private CloseableHttpResponse handleRevalidationFailure(
+ final HttpRequestWrapper request,
+ final HttpContext context,
+ final HttpCacheEntry entry,
+ final Date now) {
+ if (staleResponseNotAllowed(request, entry, now)) {
+ return generateGatewayTimeout(context);
+ } else {
+ return unvalidatedCacheHit(context, entry);
+ }
+ }
+
+ private CloseableHttpResponse generateGatewayTimeout(
+ final HttpContext context) {
+ setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
+ return Proxies.enhanceResponse(new BasicHttpResponse(
+ HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT,
+ "Gateway Timeout"));
+ }
+
+ private CloseableHttpResponse unvalidatedCacheHit(
+ final HttpContext context, final HttpCacheEntry entry) {
+ final CloseableHttpResponse cachedResponse = responseGenerator.generateResponse(entry);
+ setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
+ cachedResponse.addHeader(HeaderConstants.WARNING, "111 localhost \"Revalidation failed\"");
+ return cachedResponse;
+ }
+
+ private boolean staleResponseNotAllowed(
+ final HttpRequestWrapper request,
+ final HttpCacheEntry entry,
+ final Date now) {
+ return validityPolicy.mustRevalidate(entry)
+ || (cacheConfig.isSharedCache() && validityPolicy.proxyRevalidate(entry))
+ || explicitFreshnessRequest(request, entry, now);
+ }
+
+ private boolean mayCallBackend(final HttpRequestWrapper request) {
+ for (final Header h: request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for (final HeaderElement elt : h.getElements()) {
+ if ("only-if-cached".equals(elt.getName())) {
+ log.trace("Request marked only-if-cached");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean explicitFreshnessRequest(
+ final HttpRequestWrapper request,
+ final HttpCacheEntry entry,
+ final Date now) {
+ for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
+ try {
+ final int maxstale = Integer.parseInt(elt.getValue());
+ final long age = validityPolicy.getCurrentAgeSecs(entry, now);
+ final long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry);
+ if (age - lifetime > maxstale) {
+ return true;
+ }
+ } catch (final NumberFormatException nfe) {
+ return true;
+ }
+ } else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())
+ || HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private String generateViaHeader(final HttpMessage msg) {
+
+ final ProtocolVersion pv = msg.getProtocolVersion();
+ final String existingEntry = viaHeaders.get(pv);
+ if (existingEntry != null) {
+ return existingEntry;
+ }
+
+ final VersionInfo vi = VersionInfo.loadVersionInfo("ch.boye.httpclientandroidlib.client", getClass().getClassLoader());
+ final String release = (vi != null) ? vi.getRelease() : VersionInfo.UNAVAILABLE;
+
+ String value;
+ if ("http".equalsIgnoreCase(pv.getProtocol())) {
+ value = String.format("%d.%d localhost (Apache-HttpClient/%s (cache))", pv.getMajor(), pv.getMinor(),
+ release);
+ } else {
+ value = String.format("%s/%d.%d localhost (Apache-HttpClient/%s (cache))", pv.getProtocol(), pv.getMajor(),
+ pv.getMinor(), release);
+ }
+ viaHeaders.put(pv, value);
+
+ return value;
+ }
+
+ private void setResponseStatus(final HttpContext context, final CacheResponseStatus value) {
+ if (context != null) {
+ context.setAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS, value);
+ }
+ }
+
+ /**
+ * Reports whether this {@code CachingHttpClient} implementation
+ * supports byte-range requests as specified by the {@code Range}
+ * and {@code Content-Range} headers.
+ * @return {@code true} if byte-range requests are supported
+ */
+ public boolean supportsRangeAndContentRangeHeaders() {
+ return SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS;
+ }
+
+ Date getCurrentDate() {
+ return new Date();
+ }
+
+ boolean clientRequestsOurOptions(final HttpRequest request) {
+ final RequestLine line = request.getRequestLine();
+
+ if (!HeaderConstants.OPTIONS_METHOD.equals(line.getMethod())) {
+ return false;
+ }
+
+ if (!"*".equals(line.getUri())) {
+ return false;
+ }
+
+ if (!"0".equals(request.getFirstHeader(HeaderConstants.MAX_FORWARDS).getValue())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ CloseableHttpResponse callBackend(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+
+ final Date requestDate = getCurrentDate();
+
+ log.trace("Calling the backend");
+ final CloseableHttpResponse backendResponse = backend.execute(route, request, context, execAware);
+ try {
+ backendResponse.addHeader("Via", generateViaHeader(backendResponse));
+ return handleBackendResponse(route, request, context, execAware,
+ requestDate, getCurrentDate(), backendResponse);
+ } catch (final IOException ex) {
+ backendResponse.close();
+ throw ex;
+ } catch (final RuntimeException ex) {
+ backendResponse.close();
+ throw ex;
+ }
+ }
+
+ private boolean revalidationResponseIsTooOld(final HttpResponse backendResponse,
+ final HttpCacheEntry cacheEntry) {
+ final Header entryDateHeader = cacheEntry.getFirstHeader(HTTP.DATE_HEADER);
+ final Header responseDateHeader = backendResponse.getFirstHeader(HTTP.DATE_HEADER);
+ if (entryDateHeader != null && responseDateHeader != null) {
+ final Date entryDate = DateUtils.parseDate(entryDateHeader.getValue());
+ final Date respDate = DateUtils.parseDate(responseDateHeader.getValue());
+ if (entryDate == null || respDate == null) {
+ // either backend response or cached entry did not have a valid
+ // Date header, so we can't tell if they are out of order
+ // according to the origin clock; thus we can skip the
+ // unconditional retry recommended in 13.2.6 of RFC 2616.
+ return false;
+ }
+ if (respDate.before(entryDate)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ CloseableHttpResponse negotiateResponseFromVariants(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final Map<String, Variant> variants) throws IOException, HttpException {
+ final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder
+ .buildConditionalRequestFromVariants(request, variants);
+
+ final Date requestDate = getCurrentDate();
+ final CloseableHttpResponse backendResponse = backend.execute(
+ route, conditionalRequest, context, execAware);
+ try {
+ final Date responseDate = getCurrentDate();
+
+ backendResponse.addHeader("Via", generateViaHeader(backendResponse));
+
+ if (backendResponse.getStatusLine().getStatusCode() != HttpStatus.SC_NOT_MODIFIED) {
+ return handleBackendResponse(
+ route, request, context, execAware,
+ requestDate, responseDate, backendResponse);
+ }
+
+ final Header resultEtagHeader = backendResponse.getFirstHeader(HeaderConstants.ETAG);
+ if (resultEtagHeader == null) {
+ log.warn("304 response did not contain ETag");
+ IOUtils.consume(backendResponse.getEntity());
+ backendResponse.close();
+ return callBackend(route, request, context, execAware);
+ }
+
+ final String resultEtag = resultEtagHeader.getValue();
+ final Variant matchingVariant = variants.get(resultEtag);
+ if (matchingVariant == null) {
+ log.debug("304 response did not contain ETag matching one sent in If-None-Match");
+ IOUtils.consume(backendResponse.getEntity());
+ backendResponse.close();
+ return callBackend(route, request, context, execAware);
+ }
+
+ final HttpCacheEntry matchedEntry = matchingVariant.getEntry();
+
+ if (revalidationResponseIsTooOld(backendResponse, matchedEntry)) {
+ IOUtils.consume(backendResponse.getEntity());
+ backendResponse.close();
+ return retryRequestUnconditionally(route, request, context, execAware, matchedEntry);
+ }
+
+ recordCacheUpdate(context);
+
+ final HttpCacheEntry responseEntry = getUpdatedVariantEntry(
+ context.getTargetHost(), conditionalRequest, requestDate, responseDate,
+ backendResponse, matchingVariant, matchedEntry);
+ backendResponse.close();
+
+ final CloseableHttpResponse resp = responseGenerator.generateResponse(responseEntry);
+ tryToUpdateVariantMap(context.getTargetHost(), request, matchingVariant);
+
+ if (shouldSendNotModifiedResponse(request, responseEntry)) {
+ return responseGenerator.generateNotModifiedResponse(responseEntry);
+ }
+ return resp;
+ } catch (final IOException ex) {
+ backendResponse.close();
+ throw ex;
+ } catch (final RuntimeException ex) {
+ backendResponse.close();
+ throw ex;
+ }
+ }
+
+ private CloseableHttpResponse retryRequestUnconditionally(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final HttpCacheEntry matchedEntry) throws IOException, HttpException {
+ final HttpRequestWrapper unconditional = conditionalRequestBuilder
+ .buildUnconditionalRequest(request, matchedEntry);
+ return callBackend(route, unconditional, context, execAware);
+ }
+
+ private HttpCacheEntry getUpdatedVariantEntry(
+ final HttpHost target,
+ final HttpRequestWrapper conditionalRequest,
+ final Date requestDate,
+ final Date responseDate,
+ final CloseableHttpResponse backendResponse,
+ final Variant matchingVariant,
+ final HttpCacheEntry matchedEntry) throws IOException {
+ HttpCacheEntry responseEntry = matchedEntry;
+ try {
+ responseEntry = responseCache.updateVariantCacheEntry(target, conditionalRequest,
+ matchedEntry, backendResponse, requestDate, responseDate, matchingVariant.getCacheKey());
+ } catch (final IOException ioe) {
+ log.warn("Could not update cache entry", ioe);
+ } finally {
+ backendResponse.close();
+ }
+ return responseEntry;
+ }
+
+ private void tryToUpdateVariantMap(
+ final HttpHost target,
+ final HttpRequestWrapper request,
+ final Variant matchingVariant) {
+ try {
+ responseCache.reuseVariantEntryFor(target, request, matchingVariant);
+ } catch (final IOException ioe) {
+ log.warn("Could not update cache entry to reuse variant", ioe);
+ }
+ }
+
+ private boolean shouldSendNotModifiedResponse(
+ final HttpRequestWrapper request,
+ final HttpCacheEntry responseEntry) {
+ return (suitabilityChecker.isConditional(request)
+ && suitabilityChecker.allConditionalsMatch(request, responseEntry, new Date()));
+ }
+
+ CloseableHttpResponse revalidateCacheEntry(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final HttpCacheEntry cacheEntry) throws IOException, HttpException {
+
+ final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
+
+ Date requestDate = getCurrentDate();
+ CloseableHttpResponse backendResponse = backend.execute(
+ route, conditionalRequest, context, execAware);
+ Date responseDate = getCurrentDate();
+
+ if (revalidationResponseIsTooOld(backendResponse, cacheEntry)) {
+ backendResponse.close();
+ final HttpRequestWrapper unconditional = conditionalRequestBuilder
+ .buildUnconditionalRequest(request, cacheEntry);
+ requestDate = getCurrentDate();
+ backendResponse = backend.execute(route, unconditional, context, execAware);
+ responseDate = getCurrentDate();
+ }
+
+ backendResponse.addHeader(HeaderConstants.VIA, generateViaHeader(backendResponse));
+
+ final int statusCode = backendResponse.getStatusLine().getStatusCode();
+ if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
+ recordCacheUpdate(context);
+ }
+
+ if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
+ final HttpCacheEntry updatedEntry = responseCache.updateCacheEntry(
+ context.getTargetHost(), request, cacheEntry,
+ backendResponse, requestDate, responseDate);
+ if (suitabilityChecker.isConditional(request)
+ && suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date())) {
+ return responseGenerator
+ .generateNotModifiedResponse(updatedEntry);
+ }
+ return responseGenerator.generateResponse(updatedEntry);
+ }
+
+ if (staleIfErrorAppliesTo(statusCode)
+ && !staleResponseNotAllowed(request, cacheEntry, getCurrentDate())
+ && validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)) {
+ try {
+ final CloseableHttpResponse cachedResponse = responseGenerator.generateResponse(cacheEntry);
+ cachedResponse.addHeader(HeaderConstants.WARNING, "110 localhost \"Response is stale\"");
+ return cachedResponse;
+ } finally {
+ backendResponse.close();
+ }
+ }
+ return handleBackendResponse(
+ route, conditionalRequest, context, execAware,
+ requestDate, responseDate, backendResponse);
+ }
+
+ private boolean staleIfErrorAppliesTo(final int statusCode) {
+ return statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR
+ || statusCode == HttpStatus.SC_BAD_GATEWAY
+ || statusCode == HttpStatus.SC_SERVICE_UNAVAILABLE
+ || statusCode == HttpStatus.SC_GATEWAY_TIMEOUT;
+ }
+
+ CloseableHttpResponse handleBackendResponse(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware,
+ final Date requestDate,
+ final Date responseDate,
+ final CloseableHttpResponse backendResponse) throws IOException {
+
+ log.trace("Handling Backend response");
+ responseCompliance.ensureProtocolCompliance(request, backendResponse);
+
+ final HttpHost target = context.getTargetHost();
+ final boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse);
+ responseCache.flushInvalidatedCacheEntriesFor(target, request, backendResponse);
+ if (cacheable && !alreadyHaveNewerCacheEntry(target, request, backendResponse)) {
+ storeRequestIfModifiedSinceFor304Response(request, backendResponse);
+ return responseCache.cacheAndReturnResponse(target, request,
+ backendResponse, requestDate, responseDate);
+ }
+ if (!cacheable) {
+ try {
+ responseCache.flushCacheEntriesFor(target, request);
+ } catch (final IOException ioe) {
+ log.warn("Unable to flush invalid cache entries", ioe);
+ }
+ }
+ return backendResponse;
+ }
+
+ /**
+ * For 304 Not modified responses, adds a "Last-Modified" header with the
+ * value of the "If-Modified-Since" header passed in the request. This
+ * header is required to be able to reuse match the cache entry for
+ * subsequent requests but as defined in http specifications it is not
+ * included in 304 responses by backend servers. This header will not be
+ * included in the resulting response.
+ */
+ private void storeRequestIfModifiedSinceFor304Response(
+ final HttpRequest request, final HttpResponse backendResponse) {
+ if (backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+ final Header h = request.getFirstHeader("If-Modified-Since");
+ if (h != null) {
+ backendResponse.addHeader("Last-Modified", h.getValue());
+ }
+ }
+ }
+
+ private boolean alreadyHaveNewerCacheEntry(final HttpHost target, final HttpRequestWrapper request,
+ final HttpResponse backendResponse) {
+ HttpCacheEntry existing = null;
+ try {
+ existing = responseCache.getCacheEntry(target, request);
+ } catch (final IOException ioe) {
+ // nop
+ }
+ if (existing == null) {
+ return false;
+ }
+ final Header entryDateHeader = existing.getFirstHeader(HTTP.DATE_HEADER);
+ if (entryDateHeader == null) {
+ return false;
+ }
+ final Header responseDateHeader = backendResponse.getFirstHeader(HTTP.DATE_HEADER);
+ if (responseDateHeader == null) {
+ return false;
+ }
+ final Date entryDate = DateUtils.parseDate(entryDateHeader.getValue());
+ final Date responseDate = DateUtils.parseDate(responseDateHeader.getValue());
+ if (entryDate == null || responseDate == null) {
+ return false;
+ }
+ return responseDate.before(entryDate);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClientBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClientBuilder.java
new file mode 100644
index 000000000..385324f32
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClientBuilder.java
@@ -0,0 +1,149 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.File;
+
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheInvalidator;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage;
+import ch.boye.httpclientandroidlib.client.cache.ResourceFactory;
+import ch.boye.httpclientandroidlib.impl.client.HttpClientBuilder;
+import ch.boye.httpclientandroidlib.impl.execchain.ClientExecChain;
+
+/**
+ * Builder for {@link ch.boye.httpclientandroidlib.impl.client.CloseableHttpClient}
+ * instances capable of client-side caching.
+ *
+ * @since 4.3
+ */
+public class CachingHttpClientBuilder extends HttpClientBuilder {
+
+ private ResourceFactory resourceFactory;
+ private HttpCacheStorage storage;
+ private File cacheDir;
+ private CacheConfig cacheConfig;
+ private SchedulingStrategy schedulingStrategy;
+ private HttpCacheInvalidator httpCacheInvalidator;
+
+ public static CachingHttpClientBuilder create() {
+ return new CachingHttpClientBuilder();
+ }
+
+ protected CachingHttpClientBuilder() {
+ super();
+ }
+
+ public final CachingHttpClientBuilder setResourceFactory(
+ final ResourceFactory resourceFactory) {
+ this.resourceFactory = resourceFactory;
+ return this;
+ }
+
+ public final CachingHttpClientBuilder setHttpCacheStorage(
+ final HttpCacheStorage storage) {
+ this.storage = storage;
+ return this;
+ }
+
+ public final CachingHttpClientBuilder setCacheDir(
+ final File cacheDir) {
+ this.cacheDir = cacheDir;
+ return this;
+ }
+
+ public final CachingHttpClientBuilder setCacheConfig(
+ final CacheConfig cacheConfig) {
+ this.cacheConfig = cacheConfig;
+ return this;
+ }
+
+ public final CachingHttpClientBuilder setSchedulingStrategy(
+ final SchedulingStrategy schedulingStrategy) {
+ this.schedulingStrategy = schedulingStrategy;
+ return this;
+ }
+
+ public final CachingHttpClientBuilder setHttpCacheInvalidator(
+ final HttpCacheInvalidator cacheInvalidator) {
+ this.httpCacheInvalidator = cacheInvalidator;
+ return this;
+ }
+
+ @Override
+ protected ClientExecChain decorateMainExec(final ClientExecChain mainExec) {
+ final CacheConfig config = this.cacheConfig != null ? this.cacheConfig : CacheConfig.DEFAULT;
+ ResourceFactory resourceFactory = this.resourceFactory;
+ if (resourceFactory == null) {
+ if (this.cacheDir == null) {
+ resourceFactory = new HeapResourceFactory();
+ } else {
+ resourceFactory = new FileResourceFactory(cacheDir);
+ }
+ }
+ HttpCacheStorage storage = this.storage;
+ if (storage == null) {
+ if (this.cacheDir == null) {
+ storage = new BasicHttpCacheStorage(config);
+ } else {
+ final ManagedHttpCacheStorage managedStorage = new ManagedHttpCacheStorage(config);
+ addCloseable(managedStorage);
+ storage = managedStorage;
+ }
+ }
+ final AsynchronousValidator revalidator = createAsynchronousRevalidator(config);
+ final CacheKeyGenerator uriExtractor = new CacheKeyGenerator();
+
+ HttpCacheInvalidator cacheInvalidator = this.httpCacheInvalidator;
+ if (cacheInvalidator == null) {
+ cacheInvalidator = new CacheInvalidator(uriExtractor, storage);
+ }
+
+ return new CachingExec(mainExec,
+ new BasicHttpCache(
+ resourceFactory,
+ storage, config,
+ uriExtractor,
+ cacheInvalidator), config, revalidator);
+ }
+
+ private AsynchronousValidator createAsynchronousRevalidator(final CacheConfig config) {
+ if (config.getAsynchronousWorkersMax() > 0) {
+ final SchedulingStrategy configuredSchedulingStrategy = createSchedulingStrategy(config);
+ final AsynchronousValidator revalidator = new AsynchronousValidator(
+ configuredSchedulingStrategy);
+ addCloseable(revalidator);
+ return revalidator;
+ }
+ return null;
+ }
+
+ @SuppressWarnings("resource")
+ private SchedulingStrategy createSchedulingStrategy(final CacheConfig config) {
+ return schedulingStrategy != null ? schedulingStrategy : new ImmediateSchedulingStrategy(config);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClients.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClients.java
new file mode 100644
index 000000000..328c147f3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CachingHttpClients.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.File;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.impl.client.CloseableHttpClient;
+
+/**
+ * Factory methods for {@link CloseableHttpClient} instances
+ * capable of client-side caching.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class CachingHttpClients {
+
+ private CachingHttpClients() {
+ super();
+ }
+
+ /**
+ * Creates builder object for construction of custom
+ * {@link CloseableHttpClient} instances.
+ */
+ public static CachingHttpClientBuilder custom() {
+ return CachingHttpClientBuilder.create();
+ }
+
+ /**
+ * Creates {@link CloseableHttpClient} instance that uses a memory bound
+ * response cache.
+ */
+ public static CloseableHttpClient createMemoryBound() {
+ return CachingHttpClientBuilder.create().build();
+ }
+
+ /**
+ * Creates {@link CloseableHttpClient} instance that uses a file system
+ * bound response cache.
+ *
+ * @param cacheDir location of response cache.
+ */
+ public static CloseableHttpClient createFileBound(final File cacheDir) {
+ return CachingHttpClientBuilder.create().setCacheDir(cacheDir).build();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CombinedEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CombinedEntity.java
new file mode 100644
index 000000000..62bfaff3e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/CombinedEntity.java
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.SequenceInputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.entity.AbstractHttpEntity;
+import ch.boye.httpclientandroidlib.util.Args;
+
+@NotThreadSafe
+class CombinedEntity extends AbstractHttpEntity {
+
+ private final Resource resource;
+ private final InputStream combinedStream;
+
+ CombinedEntity(final Resource resource, final InputStream instream) throws IOException {
+ super();
+ this.resource = resource;
+ this.combinedStream = new SequenceInputStream(
+ new ResourceStream(resource.getInputStream()), instream);
+ }
+
+ public long getContentLength() {
+ return -1;
+ }
+
+ public boolean isRepeatable() {
+ return false;
+ }
+
+ public boolean isStreaming() {
+ return true;
+ }
+
+ public InputStream getContent() throws IOException, IllegalStateException {
+ return this.combinedStream;
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ Args.notNull(outstream, "Output stream");
+ final InputStream instream = getContent();
+ try {
+ int l;
+ final byte[] tmp = new byte[2048];
+ while ((l = instream.read(tmp)) != -1) {
+ outstream.write(tmp, 0, l);
+ }
+ } finally {
+ instream.close();
+ }
+ }
+
+ private void dispose() {
+ this.resource.dispose();
+ }
+
+ class ResourceStream extends FilterInputStream {
+
+ protected ResourceStream(final InputStream in) {
+ super(in);
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ super.close();
+ } finally {
+ dispose();
+ }
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ConditionalRequestBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ConditionalRequestBuilder.java
new file mode 100644
index 000000000..0edc4fb85
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ConditionalRequestBuilder.java
@@ -0,0 +1,140 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+
+/**
+ * @since 4.1
+ */
+@Immutable
+class ConditionalRequestBuilder {
+
+ /**
+ * When a {@link HttpCacheEntry} is stale but 'might' be used as a response
+ * to an {@link ch.boye.httpclientandroidlib.HttpRequest} we will attempt to revalidate
+ * the entry with the origin. Build the origin {@link ch.boye.httpclientandroidlib.HttpRequest}
+ * here and return it.
+ *
+ * @param request the original request from the caller
+ * @param cacheEntry the entry that needs to be re-validated
+ * @return the wrapped request
+ * @throws ProtocolException when I am unable to build a new origin request.
+ */
+ public HttpRequestWrapper buildConditionalRequest(final HttpRequestWrapper request, final HttpCacheEntry cacheEntry)
+ throws ProtocolException {
+ final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal());
+ newRequest.setHeaders(request.getAllHeaders());
+ final Header eTag = cacheEntry.getFirstHeader(HeaderConstants.ETAG);
+ if (eTag != null) {
+ newRequest.setHeader(HeaderConstants.IF_NONE_MATCH, eTag.getValue());
+ }
+ final Header lastModified = cacheEntry.getFirstHeader(HeaderConstants.LAST_MODIFIED);
+ if (lastModified != null) {
+ newRequest.setHeader(HeaderConstants.IF_MODIFIED_SINCE, lastModified.getValue());
+ }
+ boolean mustRevalidate = false;
+ for(final Header h : cacheEntry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE.equalsIgnoreCase(elt.getName())
+ || HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE.equalsIgnoreCase(elt.getName())) {
+ mustRevalidate = true;
+ break;
+ }
+ }
+ }
+ if (mustRevalidate) {
+ newRequest.addHeader(HeaderConstants.CACHE_CONTROL, HeaderConstants.CACHE_CONTROL_MAX_AGE + "=0");
+ }
+ return newRequest;
+
+ }
+
+ /**
+ * When a {@link HttpCacheEntry} does not exist for a specific
+ * {@link ch.boye.httpclientandroidlib.HttpRequest} we attempt to see if an existing
+ * {@link HttpCacheEntry} is appropriate by building a conditional
+ * {@link ch.boye.httpclientandroidlib.HttpRequest} using the variants' ETag values.
+ * If no such values exist, the request is unmodified
+ *
+ * @param request the original request from the caller
+ * @param variants
+ * @return the wrapped request
+ */
+ public HttpRequestWrapper buildConditionalRequestFromVariants(final HttpRequestWrapper request,
+ final Map<String, Variant> variants) {
+ final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal());
+ newRequest.setHeaders(request.getAllHeaders());
+
+ // we do not support partial content so all etags are used
+ final StringBuilder etags = new StringBuilder();
+ boolean first = true;
+ for(final String etag : variants.keySet()) {
+ if (!first) {
+ etags.append(",");
+ }
+ first = false;
+ etags.append(etag);
+ }
+
+ newRequest.setHeader(HeaderConstants.IF_NONE_MATCH, etags.toString());
+ return newRequest;
+ }
+
+ /**
+ * Returns a request to unconditionally validate a cache entry with
+ * the origin. In certain cases (due to multiple intervening caches)
+ * our cache may actually receive a response to a normal conditional
+ * validation where the Date header is actually older than that of
+ * our current cache entry. In this case, the protocol recommendation
+ * is to retry the validation and force syncup with the origin.
+ * @param request client request we are trying to satisfy
+ * @param entry existing cache entry we are trying to validate
+ * @return an unconditional validation request
+ */
+ public HttpRequestWrapper buildUnconditionalRequest(final HttpRequestWrapper request, final HttpCacheEntry entry) {
+ final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(request.getOriginal());
+ newRequest.setHeaders(request.getAllHeaders());
+ newRequest.addHeader(HeaderConstants.CACHE_CONTROL,HeaderConstants.CACHE_CONTROL_NO_CACHE);
+ newRequest.addHeader(HeaderConstants.PRAGMA,HeaderConstants.CACHE_CONTROL_NO_CACHE);
+ newRequest.removeHeaders(HeaderConstants.IF_RANGE);
+ newRequest.removeHeaders(HeaderConstants.IF_MATCH);
+ newRequest.removeHeaders(HeaderConstants.IF_NONE_MATCH);
+ newRequest.removeHeaders(HeaderConstants.IF_UNMODIFIED_SINCE);
+ newRequest.removeHeaders(HeaderConstants.IF_MODIFIED_SINCE);
+ return newRequest;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultFailureCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultFailureCache.java
new file mode 100644
index 000000000..3646c3c32
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultFailureCache.java
@@ -0,0 +1,143 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Implements a bounded failure cache. The oldest entries are discarded when
+ * the maximum size is exceeded.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public class DefaultFailureCache implements FailureCache {
+
+ static final int DEFAULT_MAX_SIZE = 1000;
+ static final int MAX_UPDATE_TRIES = 10;
+
+ private final int maxSize;
+ private final ConcurrentMap<String, FailureCacheValue> storage;
+
+ /**
+ * Create a new failure cache with the maximum size of
+ * {@link #DEFAULT_MAX_SIZE}.
+ */
+ public DefaultFailureCache() {
+ this(DEFAULT_MAX_SIZE);
+ }
+
+ /**
+ * Creates a new failure cache with the specified maximum size.
+ * @param maxSize the maximum number of entries the cache should store
+ */
+ public DefaultFailureCache(final int maxSize) {
+ this.maxSize = maxSize;
+ this.storage = new ConcurrentHashMap<String, FailureCacheValue>();
+ }
+
+ public int getErrorCount(final String identifier) {
+ if (identifier == null) {
+ throw new IllegalArgumentException("identifier may not be null");
+ }
+ final FailureCacheValue storedErrorCode = storage.get(identifier);
+ return storedErrorCode != null ? storedErrorCode.getErrorCount() : 0;
+ }
+
+ public void resetErrorCount(final String identifier) {
+ if (identifier == null) {
+ throw new IllegalArgumentException("identifier may not be null");
+ }
+ storage.remove(identifier);
+ }
+
+ public void increaseErrorCount(final String identifier) {
+ if (identifier == null) {
+ throw new IllegalArgumentException("identifier may not be null");
+ }
+ updateValue(identifier);
+ removeOldestEntryIfMapSizeExceeded();
+ }
+
+ private void updateValue(final String identifier) {
+ /**
+ * Due to concurrency it is possible that someone else is modifying an
+ * entry before we could write back our updated value. So we keep
+ * trying until it is our turn.
+ *
+ * In case there is a lot of contention on that identifier, a thread
+ * might starve. Thus it gives up after a certain number of failed
+ * update tries.
+ */
+ for (int i = 0; i < MAX_UPDATE_TRIES; i++) {
+ final FailureCacheValue oldValue = storage.get(identifier);
+ if (oldValue == null) {
+ final FailureCacheValue newValue = new FailureCacheValue(identifier, 1);
+ if (storage.putIfAbsent(identifier, newValue) == null) {
+ return;
+ }
+ }
+ else {
+ final int errorCount = oldValue.getErrorCount();
+ if (errorCount == Integer.MAX_VALUE) {
+ return;
+ }
+ final FailureCacheValue newValue = new FailureCacheValue(identifier, errorCount + 1);
+ if (storage.replace(identifier, oldValue, newValue)) {
+ return;
+ }
+ }
+ }
+ }
+
+ private void removeOldestEntryIfMapSizeExceeded() {
+ if (storage.size() > maxSize) {
+ final FailureCacheValue valueWithOldestTimestamp = findValueWithOldestTimestamp();
+ if (valueWithOldestTimestamp != null) {
+ storage.remove(valueWithOldestTimestamp.getKey(), valueWithOldestTimestamp);
+ }
+ }
+ }
+
+ private FailureCacheValue findValueWithOldestTimestamp() {
+ long oldestTimestamp = Long.MAX_VALUE;
+ FailureCacheValue oldestValue = null;
+ for (final Map.Entry<String, FailureCacheValue> storageEntry : storage.entrySet()) {
+ final FailureCacheValue value = storageEntry.getValue();
+ final long creationTimeInNanos = value.getCreationTimeInNanos();
+ if (creationTimeInNanos < oldestTimestamp) {
+ oldestTimestamp = creationTimeInNanos;
+ oldestValue = storageEntry.getValue();
+ }
+ }
+ return oldestValue;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultHttpCacheEntrySerializer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultHttpCacheEntrySerializer.java
new file mode 100644
index 000000000..0d78a2eb1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/DefaultHttpCacheEntrySerializer.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntrySerializationException;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntrySerializer;
+
+/**
+ * {@link HttpCacheEntrySerializer} implementation that uses the default (native)
+ * serialization.
+ *
+ * @see java.io.Serializable
+ *
+ * @since 4.1
+ */
+@Immutable
+public class DefaultHttpCacheEntrySerializer implements HttpCacheEntrySerializer {
+
+ public void writeTo(final HttpCacheEntry cacheEntry, final OutputStream os) throws IOException {
+ final ObjectOutputStream oos = new ObjectOutputStream(os);
+ try {
+ oos.writeObject(cacheEntry);
+ } finally {
+ oos.close();
+ }
+ }
+
+ public HttpCacheEntry readFrom(final InputStream is) throws IOException {
+ final ObjectInputStream ois = new ObjectInputStream(is);
+ try {
+ return (HttpCacheEntry) ois.readObject();
+ } catch (final ClassNotFoundException ex) {
+ throw new HttpCacheEntrySerializationException("Class not found: " + ex.getMessage(), ex);
+ } finally {
+ ois.close();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ExponentialBackOffSchedulingStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ExponentialBackOffSchedulingStrategy.java
new file mode 100644
index 000000000..286205583
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ExponentialBackOffSchedulingStrategy.java
@@ -0,0 +1,174 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An implementation that backs off exponentially based on the number of
+ * consecutive failed attempts stored in the
+ * {@link AsynchronousValidationRequest}. It uses the following defaults:
+ * <pre>
+ * no delay in case it was never tried or didn't fail so far
+ * 6 secs delay for one failed attempt (= {@link #getInitialExpiryInMillis()})
+ * 60 secs delay for two failed attempts
+ * 10 mins delay for three failed attempts
+ * 100 mins delay for four failed attempts
+ * ~16 hours delay for five failed attempts
+ * 24 hours delay for six or more failed attempts (= {@link #getMaxExpiryInMillis()})
+ * </pre>
+ *
+ * The following equation is used to calculate the delay for a specific revalidation request:
+ * <pre>
+ * delay = {@link #getInitialExpiryInMillis()} * Math.pow({@link #getBackOffRate()}, {@link AsynchronousValidationRequest#getConsecutiveFailedAttempts()} - 1))
+ * </pre>
+ * The resulting delay won't exceed {@link #getMaxExpiryInMillis()}.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public class ExponentialBackOffSchedulingStrategy implements SchedulingStrategy {
+
+ public static final long DEFAULT_BACK_OFF_RATE = 10;
+ public static final long DEFAULT_INITIAL_EXPIRY_IN_MILLIS = TimeUnit.SECONDS.toMillis(6);
+ public static final long DEFAULT_MAX_EXPIRY_IN_MILLIS = TimeUnit.SECONDS.toMillis(86400);
+
+ private final long backOffRate;
+ private final long initialExpiryInMillis;
+ private final long maxExpiryInMillis;
+
+ private final ScheduledExecutorService executor;
+
+ /**
+ * Create a new scheduling strategy using a fixed pool of worker threads.
+ * @param cacheConfig the thread pool configuration to be used; not <code>null</code>
+ * @see ch.boye.httpclientandroidlib.impl.client.cache.CacheConfig#getAsynchronousWorkersMax()
+ * @see #DEFAULT_BACK_OFF_RATE
+ * @see #DEFAULT_INITIAL_EXPIRY_IN_MILLIS
+ * @see #DEFAULT_MAX_EXPIRY_IN_MILLIS
+ */
+ public ExponentialBackOffSchedulingStrategy(final CacheConfig cacheConfig) {
+ this(cacheConfig,
+ DEFAULT_BACK_OFF_RATE,
+ DEFAULT_INITIAL_EXPIRY_IN_MILLIS,
+ DEFAULT_MAX_EXPIRY_IN_MILLIS);
+ }
+
+ /**
+ * Create a new scheduling strategy by using a fixed pool of worker threads and the
+ * given parameters to calculated the delay.
+ *
+ * @param cacheConfig the thread pool configuration to be used; not <code>null</code>
+ * @param backOffRate the back off rate to be used; not negative
+ * @param initialExpiryInMillis the initial expiry in milli seconds; not negative
+ * @param maxExpiryInMillis the upper limit of the delay in milli seconds; not negative
+ * @see ch.boye.httpclientandroidlib.impl.client.cache.CacheConfig#getAsynchronousWorkersMax()
+ * @see ExponentialBackOffSchedulingStrategy
+ */
+ public ExponentialBackOffSchedulingStrategy(
+ final CacheConfig cacheConfig,
+ final long backOffRate,
+ final long initialExpiryInMillis,
+ final long maxExpiryInMillis) {
+ this(createThreadPoolFromCacheConfig(cacheConfig),
+ backOffRate,
+ initialExpiryInMillis,
+ maxExpiryInMillis);
+ }
+
+ private static ScheduledThreadPoolExecutor createThreadPoolFromCacheConfig(
+ final CacheConfig cacheConfig) {
+ final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(
+ cacheConfig.getAsynchronousWorkersMax());
+ scheduledThreadPoolExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+ return scheduledThreadPoolExecutor;
+ }
+
+ ExponentialBackOffSchedulingStrategy(
+ final ScheduledExecutorService executor,
+ final long backOffRate,
+ final long initialExpiryInMillis,
+ final long maxExpiryInMillis) {
+ this.executor = checkNotNull("executor", executor);
+ this.backOffRate = checkNotNegative("backOffRate", backOffRate);
+ this.initialExpiryInMillis = checkNotNegative("initialExpiryInMillis", initialExpiryInMillis);
+ this.maxExpiryInMillis = checkNotNegative("maxExpiryInMillis", maxExpiryInMillis);
+ }
+
+ public void schedule(
+ final AsynchronousValidationRequest revalidationRequest) {
+ checkNotNull("revalidationRequest", revalidationRequest);
+ final int consecutiveFailedAttempts = revalidationRequest.getConsecutiveFailedAttempts();
+ final long delayInMillis = calculateDelayInMillis(consecutiveFailedAttempts);
+ executor.schedule(revalidationRequest, delayInMillis, TimeUnit.MILLISECONDS);
+ }
+
+ public void close() {
+ executor.shutdown();
+ }
+
+ public long getBackOffRate() {
+ return backOffRate;
+ }
+
+ public long getInitialExpiryInMillis() {
+ return initialExpiryInMillis;
+ }
+
+ public long getMaxExpiryInMillis() {
+ return maxExpiryInMillis;
+ }
+
+ protected long calculateDelayInMillis(final int consecutiveFailedAttempts) {
+ if (consecutiveFailedAttempts > 0) {
+ final long delayInSeconds = (long) (initialExpiryInMillis *
+ Math.pow(backOffRate, consecutiveFailedAttempts - 1));
+ return Math.min(delayInSeconds, maxExpiryInMillis);
+ }
+ else {
+ return 0;
+ }
+ }
+
+ protected static <T> T checkNotNull(final String parameterName, final T value) {
+ if (value == null) {
+ throw new IllegalArgumentException(parameterName + " may not be null");
+ }
+ return value;
+ }
+
+ protected static long checkNotNegative(final String parameterName, final long value) {
+ if (value < 0) {
+ throw new IllegalArgumentException(parameterName + " may not be negative");
+ }
+ return value;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCache.java
new file mode 100644
index 000000000..a30fc54d9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCache.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+/**
+ * Increase and reset the number of errors associated with a specific
+ * identifier.
+ *
+ * @since 4.3
+ */
+public interface FailureCache {
+
+ /**
+ * Get the current error count.
+ * @param identifier the identifier for which the error count is requested
+ * @return the currently known error count or zero if there is no record
+ */
+ int getErrorCount(String identifier);
+
+ /**
+ * Reset the error count back to zero.
+ * @param identifier the identifier for which the error count should be
+ * reset
+ */
+ void resetErrorCount(String identifier);
+
+ /**
+ * Increases the error count by one.
+ * @param identifier the identifier for which the error count should be
+ * increased
+ */
+ void increaseErrorCount(String identifier);
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCacheValue.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCacheValue.java
new file mode 100644
index 000000000..48bbf55fc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FailureCacheValue.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * The error count with a creation timestamp and its associated key.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class FailureCacheValue {
+
+ private final long creationTimeInNanos;
+ private final String key;
+ private final int errorCount;
+
+ public FailureCacheValue(final String key, final int errorCount) {
+ this.creationTimeInNanos = System.nanoTime();
+ this.key = key;
+ this.errorCount = errorCount;
+ }
+
+ public long getCreationTimeInNanos() {
+ return creationTimeInNanos;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public int getErrorCount() {
+ return errorCount;
+ }
+
+ @Override
+ public String toString() {
+ return "[entry creationTimeInNanos=" + creationTimeInNanos + "; " +
+ "key=" + key + "; errorCount=" + errorCount + ']';
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResource.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResource.java
new file mode 100644
index 000000000..934ecd13d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResource.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+
+/**
+ * Cache resource backed by a file.
+ *
+ * @since 4.1
+ */
+@ThreadSafe
+public class FileResource implements Resource {
+
+ private static final long serialVersionUID = 4132244415919043397L;
+
+ private final File file;
+
+ private volatile boolean disposed;
+
+ public FileResource(final File file) {
+ super();
+ this.file = file;
+ this.disposed = false;
+ }
+
+ synchronized File getFile() {
+ return this.file;
+ }
+
+ public synchronized InputStream getInputStream() throws IOException {
+ return new FileInputStream(this.file);
+ }
+
+ public synchronized long length() {
+ return this.file.length();
+ }
+
+ public synchronized void dispose() {
+ if (this.disposed) {
+ return;
+ }
+ this.disposed = true;
+ this.file.delete();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResourceFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResourceFactory.java
new file mode 100644
index 000000000..8522c54b5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/FileResourceFactory.java
@@ -0,0 +1,111 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.InputLimit;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.client.cache.ResourceFactory;
+
+/**
+ * Generates {@link Resource} instances whose body is stored in a temporary file.
+ *
+ * @since 4.1
+ */
+@Immutable
+public class FileResourceFactory implements ResourceFactory {
+
+ private final File cacheDir;
+ private final BasicIdGenerator idgen;
+
+ public FileResourceFactory(final File cacheDir) {
+ super();
+ this.cacheDir = cacheDir;
+ this.idgen = new BasicIdGenerator();
+ }
+
+ private File generateUniqueCacheFile(final String requestId) {
+ final StringBuilder buffer = new StringBuilder();
+ this.idgen.generate(buffer);
+ buffer.append('.');
+ final int len = Math.min(requestId.length(), 100);
+ for (int i = 0; i < len; i++) {
+ final char ch = requestId.charAt(i);
+ if (Character.isLetterOrDigit(ch) || ch == '.') {
+ buffer.append(ch);
+ } else {
+ buffer.append('-');
+ }
+ }
+ return new File(this.cacheDir, buffer.toString());
+ }
+
+ public Resource generate(
+ final String requestId,
+ final InputStream instream,
+ final InputLimit limit) throws IOException {
+ final File file = generateUniqueCacheFile(requestId);
+ final FileOutputStream outstream = new FileOutputStream(file);
+ try {
+ final byte[] buf = new byte[2048];
+ long total = 0;
+ int l;
+ while ((l = instream.read(buf)) != -1) {
+ outstream.write(buf, 0, l);
+ total += l;
+ if (limit != null && total > limit.getValue()) {
+ limit.reached();
+ break;
+ }
+ }
+ } finally {
+ outstream.close();
+ }
+ return new FileResource(file);
+ }
+
+ public Resource copy(
+ final String requestId,
+ final Resource resource) throws IOException {
+ final File file = generateUniqueCacheFile(requestId);
+
+ if (resource instanceof FileResource) {
+ final File src = ((FileResource) resource).getFile();
+ IOUtils.copyFile(src, file);
+ } else {
+ final FileOutputStream out = new FileOutputStream(file);
+ IOUtils.copyAndClose(resource.getInputStream(), out);
+ }
+ return new FileResource(file);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResource.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResource.java
new file mode 100644
index 000000000..e4b353a3c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResource.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+
+/**
+ * Cache resource backed by a byte array on the heap.
+ *
+ * @since 4.1
+ */
+@Immutable
+public class HeapResource implements Resource {
+
+ private static final long serialVersionUID = -2078599905620463394L;
+
+ private final byte[] b;
+
+ public HeapResource(final byte[] b) {
+ super();
+ this.b = b;
+ }
+
+ byte[] getByteArray() {
+ return this.b;
+ }
+
+ public InputStream getInputStream() {
+ return new ByteArrayInputStream(this.b);
+ }
+
+ public long length() {
+ return this.b.length;
+ }
+
+ public void dispose() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResourceFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResourceFactory.java
new file mode 100644
index 000000000..f45cc0965
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HeapResourceFactory.java
@@ -0,0 +1,83 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.InputLimit;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.client.cache.ResourceFactory;
+
+/**
+ * Generates {@link Resource} instances stored entirely in heap.
+ *
+ * @since 4.1
+ */
+@Immutable
+public class HeapResourceFactory implements ResourceFactory {
+
+ public Resource generate(
+ final String requestId,
+ final InputStream instream,
+ final InputLimit limit) throws IOException {
+ final ByteArrayOutputStream outstream = new ByteArrayOutputStream();
+ final byte[] buf = new byte[2048];
+ long total = 0;
+ int l;
+ while ((l = instream.read(buf)) != -1) {
+ outstream.write(buf, 0, l);
+ total += l;
+ if (limit != null && total > limit.getValue()) {
+ limit.reached();
+ break;
+ }
+ }
+ return createResource(outstream.toByteArray());
+ }
+
+ public Resource copy(
+ final String requestId,
+ final Resource resource) throws IOException {
+ byte[] body;
+ if (resource instanceof HeapResource) {
+ body = ((HeapResource) resource).getByteArray();
+ } else {
+ final ByteArrayOutputStream outstream = new ByteArrayOutputStream();
+ IOUtils.copyAndClose(resource.getInputStream(), outstream);
+ body = outstream.toByteArray();
+ }
+ return createResource(body);
+ }
+
+ Resource createResource(final byte[] buf) {
+ return new HeapResource(buf);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HttpCache.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HttpCache.java
new file mode 100644
index 000000000..48037b5f5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/HttpCache.java
@@ -0,0 +1,166 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+
+/**
+ * @since 4.1
+ */
+interface HttpCache {
+
+ /**
+ * Clear all matching {@link HttpCacheEntry}s.
+ * @param host
+ * @param request
+ * @throws IOException
+ */
+ void flushCacheEntriesFor(HttpHost host, HttpRequest request)
+ throws IOException;
+
+ /**
+ * Clear invalidated matching {@link HttpCacheEntry}s
+ * @param host
+ * @param request
+ * @throws IOException
+ */
+ void flushInvalidatedCacheEntriesFor(HttpHost host, HttpRequest request)
+ throws IOException;
+
+ /** Clear any entries that may be invalidated by the given response to
+ * a particular request.
+ * @param host
+ * @param request
+ * @param response
+ */
+ void flushInvalidatedCacheEntriesFor(HttpHost host, HttpRequest request,
+ HttpResponse response);
+
+ /**
+ * Retrieve matching {@link HttpCacheEntry} from the cache if it exists
+ * @param host
+ * @param request
+ * @return the matching {@link HttpCacheEntry} or {@code null}
+ * @throws IOException
+ */
+ HttpCacheEntry getCacheEntry(HttpHost host, HttpRequest request)
+ throws IOException;
+
+ /**
+ * Retrieve all variants from the cache, if there are no variants then an empty
+ * {@link Map} is returned
+ * @param host
+ * @param request
+ * @return a <code>Map</code> mapping Etags to variant cache entries
+ * @throws IOException
+ */
+ Map<String,Variant> getVariantCacheEntriesWithEtags(HttpHost host, HttpRequest request)
+ throws IOException;
+
+ /**
+ * Store a {@link HttpResponse} in the cache if possible, and return
+ * @param host
+ * @param request
+ * @param originResponse
+ * @param requestSent
+ * @param responseReceived
+ * @return the {@link HttpResponse}
+ * @throws IOException
+ */
+ HttpResponse cacheAndReturnResponse(
+ HttpHost host, HttpRequest request, HttpResponse originResponse,
+ Date requestSent, Date responseReceived)
+ throws IOException;
+
+ /**
+ * Store a {@link HttpResponse} in the cache if possible, and return
+ * @param host
+ * @param request
+ * @param originResponse
+ * @param requestSent
+ * @param responseReceived
+ * @return the {@link HttpResponse}
+ * @throws IOException
+ */
+ CloseableHttpResponse cacheAndReturnResponse(HttpHost host,
+ HttpRequest request, CloseableHttpResponse originResponse,
+ Date requestSent, Date responseReceived)
+ throws IOException;
+
+ /**
+ * Update a {@link HttpCacheEntry} using a 304 {@link HttpResponse}.
+ * @param target
+ * @param request
+ * @param stale
+ * @param originResponse
+ * @param requestSent
+ * @param responseReceived
+ * @return the updated {@link HttpCacheEntry}
+ * @throws IOException
+ */
+ HttpCacheEntry updateCacheEntry(
+ HttpHost target, HttpRequest request, HttpCacheEntry stale, HttpResponse originResponse,
+ Date requestSent, Date responseReceived)
+ throws IOException;
+
+ /**
+ * Update a specific {@link HttpCacheEntry} representing a cached variant
+ * using a 304 {@link HttpResponse}.
+ * @param target host for client request
+ * @param request actual request from upstream client
+ * @param stale current variant cache entry
+ * @param originResponse 304 response received from origin
+ * @param requestSent when the validating request was sent
+ * @param responseReceived when the validating response was received
+ * @param cacheKey where in the cache this entry is currently stored
+ * @return the updated {@link HttpCacheEntry}
+ * @throws IOException
+ */
+ HttpCacheEntry updateVariantCacheEntry(HttpHost target, HttpRequest request,
+ HttpCacheEntry stale, HttpResponse originResponse, Date requestSent,
+ Date responseReceived, String cacheKey)
+ throws IOException;
+
+ /**
+ * Specifies cache should reuse the given cached variant to satisfy
+ * requests whose varying headers match those of the given client request.
+ * @param target host of the upstream client request
+ * @param req request sent by upstream client
+ * @param variant variant cache entry to reuse
+ * @throws IOException may be thrown during cache update
+ */
+ void reuseVariantEntryFor(HttpHost target, final HttpRequest req,
+ final Variant variant) throws IOException;
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/IOUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/IOUtils.java
new file mode 100644
index 000000000..aaf41b2c9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/IOUtils.java
@@ -0,0 +1,109 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+@Immutable
+class IOUtils {
+
+ static void consume(final HttpEntity entity) throws IOException {
+ if (entity == null) {
+ return;
+ }
+ if (entity.isStreaming()) {
+ final InputStream instream = entity.getContent();
+ if (instream != null) {
+ instream.close();
+ }
+ }
+ }
+
+ static void copy(final InputStream in, final OutputStream out) throws IOException {
+ final byte[] buf = new byte[2048];
+ int len;
+ while ((len = in.read(buf)) != -1) {
+ out.write(buf, 0, len);
+ }
+ }
+
+ static void closeSilently(final Closeable closable) {
+ try {
+ closable.close();
+ } catch (final IOException ignore) {
+ }
+ }
+
+ static void copyAndClose(final InputStream in, final OutputStream out) throws IOException {
+ try {
+ copy(in, out);
+ in.close();
+ out.close();
+ } catch (final IOException ex) {
+ closeSilently(in);
+ closeSilently(out);
+ // Propagate the original exception
+ throw ex;
+ }
+ }
+
+ static void copyFile(final File in, final File out) throws IOException {
+ final RandomAccessFile f1 = new RandomAccessFile(in, "r");
+ final RandomAccessFile f2 = new RandomAccessFile(out, "rw");
+ try {
+ final FileChannel c1 = f1.getChannel();
+ final FileChannel c2 = f2.getChannel();
+ try {
+ c1.transferTo(0, f1.length(), c2);
+ c1.close();
+ c2.close();
+ } catch (final IOException ex) {
+ closeSilently(c1);
+ closeSilently(c2);
+ // Propagate the original exception
+ throw ex;
+ }
+ f1.close();
+ f2.close();
+ } catch (final IOException ex) {
+ closeSilently(f1);
+ closeSilently(f2);
+ // Propagate the original exception
+ throw ex;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ImmediateSchedulingStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ImmediateSchedulingStrategy.java
new file mode 100644
index 000000000..71d633825
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ImmediateSchedulingStrategy.java
@@ -0,0 +1,88 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Immediately schedules any incoming validation request. Relies on
+ * {@link CacheConfig} to configure the used {@link java.util.concurrent.ThreadPoolExecutor}.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public class ImmediateSchedulingStrategy implements SchedulingStrategy {
+
+ private final ExecutorService executor;
+
+ /**
+ * Uses a {@link java.util.concurrent.ThreadPoolExecutor} which is configured according to the
+ * given {@link CacheConfig}.
+ * @param cacheConfig specifies thread pool settings. See
+ * {@link CacheConfig#getAsynchronousWorkersMax()},
+ * {@link CacheConfig#getAsynchronousWorkersCore()},
+ * {@link CacheConfig#getAsynchronousWorkerIdleLifetimeSecs()},
+ * and {@link CacheConfig#getRevalidationQueueSize()}.
+ */
+ public ImmediateSchedulingStrategy(final CacheConfig cacheConfig) {
+ this(new ThreadPoolExecutor(
+ cacheConfig.getAsynchronousWorkersCore(),
+ cacheConfig.getAsynchronousWorkersMax(),
+ cacheConfig.getAsynchronousWorkerIdleLifetimeSecs(),
+ TimeUnit.SECONDS,
+ new ArrayBlockingQueue<Runnable>(cacheConfig.getRevalidationQueueSize()))
+ );
+ }
+
+ ImmediateSchedulingStrategy(final ExecutorService executor) {
+ this.executor = executor;
+ }
+
+ public void schedule(final AsynchronousValidationRequest revalidationRequest) {
+ if (revalidationRequest == null) {
+ throw new IllegalArgumentException("AsynchronousValidationRequest may not be null");
+ }
+
+ executor.execute(revalidationRequest);
+ }
+
+ public void close() {
+ executor.shutdown();
+ }
+
+ /**
+ * Visible for testing.
+ */
+ void awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException {
+ executor.awaitTermination(timeout, unit);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ManagedHttpCacheStorage.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ManagedHttpCacheStorage.java
new file mode 100644
index 000000000..3a2589cc3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ManagedHttpCacheStorage.java
@@ -0,0 +1,163 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.ref.ReferenceQueue;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheStorage;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheUpdateCallback;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * {@link HttpCacheStorage} implementation capable of deallocating resources associated with
+ * the cache entries. This cache keeps track of cache entries using
+ * {@link java.lang.ref.PhantomReference} and maintains a collection of all resources that
+ * are no longer in use. The cache, however, does not automatically deallocates associated
+ * resources by invoking {@link Resource#dispose()} method. The consumer MUST periodically
+ * call {@link #cleanResources()} method to trigger resource deallocation. The cache can be
+ * permanently shut down using {@link #shutdown()} method. All resources associated with
+ * the entries used by the cache will be deallocated.
+ *
+ * This {@link HttpCacheStorage} implementation is intended for use with {@link FileResource}
+ * and similar.
+ *
+ * @since 4.1
+ */
+@ThreadSafe
+public class ManagedHttpCacheStorage implements HttpCacheStorage, Closeable {
+
+ private final CacheMap entries;
+ private final ReferenceQueue<HttpCacheEntry> morque;
+ private final Set<ResourceReference> resources;
+ private final AtomicBoolean active;
+
+ public ManagedHttpCacheStorage(final CacheConfig config) {
+ super();
+ this.entries = new CacheMap(config.getMaxCacheEntries());
+ this.morque = new ReferenceQueue<HttpCacheEntry>();
+ this.resources = new HashSet<ResourceReference>();
+ this.active = new AtomicBoolean(true);
+ }
+
+ private void ensureValidState() throws IllegalStateException {
+ if (!this.active.get()) {
+ throw new IllegalStateException("Cache has been shut down");
+ }
+ }
+
+ private void keepResourceReference(final HttpCacheEntry entry) {
+ final Resource resource = entry.getResource();
+ if (resource != null) {
+ // Must deallocate the resource when the entry is no longer in used
+ final ResourceReference ref = new ResourceReference(entry, this.morque);
+ this.resources.add(ref);
+ }
+ }
+
+ public void putEntry(final String url, final HttpCacheEntry entry) throws IOException {
+ Args.notNull(url, "URL");
+ Args.notNull(entry, "Cache entry");
+ ensureValidState();
+ synchronized (this) {
+ this.entries.put(url, entry);
+ keepResourceReference(entry);
+ }
+ }
+
+ public HttpCacheEntry getEntry(final String url) throws IOException {
+ Args.notNull(url, "URL");
+ ensureValidState();
+ synchronized (this) {
+ return this.entries.get(url);
+ }
+ }
+
+ public void removeEntry(final String url) throws IOException {
+ Args.notNull(url, "URL");
+ ensureValidState();
+ synchronized (this) {
+ // Cannot deallocate the associated resources immediately as the
+ // cache entry may still be in use
+ this.entries.remove(url);
+ }
+ }
+
+ public void updateEntry(
+ final String url,
+ final HttpCacheUpdateCallback callback) throws IOException {
+ Args.notNull(url, "URL");
+ Args.notNull(callback, "Callback");
+ ensureValidState();
+ synchronized (this) {
+ final HttpCacheEntry existing = this.entries.get(url);
+ final HttpCacheEntry updated = callback.update(existing);
+ this.entries.put(url, updated);
+ if (existing != updated) {
+ keepResourceReference(updated);
+ }
+ }
+ }
+
+ public void cleanResources() {
+ if (this.active.get()) {
+ ResourceReference ref;
+ while ((ref = (ResourceReference) this.morque.poll()) != null) {
+ synchronized (this) {
+ this.resources.remove(ref);
+ }
+ ref.getResource().dispose();
+ }
+ }
+ }
+
+ public void shutdown() {
+ if (this.active.compareAndSet(true, false)) {
+ synchronized (this) {
+ this.entries.clear();
+ for (final ResourceReference ref: this.resources) {
+ ref.getResource().dispose();
+ }
+ this.resources.clear();
+ while (this.morque.poll() != null) {
+ }
+ }
+ }
+ }
+
+ public void close() {
+ shutdown();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/OptionsHttp11Response.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/OptionsHttp11Response.java
new file mode 100644
index 000000000..c2e07b52d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/OptionsHttp11Response.java
@@ -0,0 +1,182 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.message.AbstractHttpMessage;
+import ch.boye.httpclientandroidlib.message.BasicStatusLine;
+import ch.boye.httpclientandroidlib.params.BasicHttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * @since 4.1
+ */
+@SuppressWarnings("deprecation")
+@Immutable
+final class OptionsHttp11Response extends AbstractHttpMessage implements HttpResponse {
+
+ private final StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_NOT_IMPLEMENTED, "");
+ private final ProtocolVersion version = HttpVersion.HTTP_1_1;
+
+ public StatusLine getStatusLine() {
+ return statusLine;
+ }
+
+ public void setStatusLine(final StatusLine statusline) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ public void setStatusLine(final ProtocolVersion ver, final int code) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ public void setStatusLine(final ProtocolVersion ver, final int code, final String reason) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ public void setStatusCode(final int code) throws IllegalStateException {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ public void setReasonPhrase(final String reason) throws IllegalStateException {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ public HttpEntity getEntity() {
+ return null;
+ }
+
+ public void setEntity(final HttpEntity entity) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ public Locale getLocale() {
+ return null;
+ }
+
+ public void setLocale(final Locale loc) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ return version;
+ }
+
+ @Override
+ public boolean containsHeader(final String name) {
+ return this.headergroup.containsHeader(name);
+ }
+
+ @Override
+ public Header[] getHeaders(final String name) {
+ return this.headergroup.getHeaders(name);
+ }
+
+ @Override
+ public Header getFirstHeader(final String name) {
+ return this.headergroup.getFirstHeader(name);
+ }
+
+ @Override
+ public Header getLastHeader(final String name) {
+ return this.headergroup.getLastHeader(name);
+ }
+
+ @Override
+ public Header[] getAllHeaders() {
+ return this.headergroup.getAllHeaders();
+ }
+
+ @Override
+ public void addHeader(final Header header) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ @Override
+ public void addHeader(final String name, final String value) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ @Override
+ public void setHeader(final Header header) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ @Override
+ public void setHeader(final String name, final String value) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ @Override
+ public void setHeaders(final Header[] headers) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ @Override
+ public void removeHeader(final Header header) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ @Override
+ public void removeHeaders(final String name) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+
+ @Override
+ public HeaderIterator headerIterator() {
+ return this.headergroup.iterator();
+ }
+
+ @Override
+ public HeaderIterator headerIterator(final String name) {
+ return this.headergroup.iterator(name);
+ }
+
+ @Override
+ public HttpParams getParams() {
+ if (this.params == null) {
+ this.params = new BasicHttpParams();
+ }
+ return this.params;
+ }
+
+ @Override
+ public void setParams(final HttpParams params) {
+ // No-op on purpose, this class is not going to be doing any work.
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Proxies.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Proxies.java
new file mode 100644
index 000000000..4499d8288
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Proxies.java
@@ -0,0 +1,56 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.lang.reflect.Proxy;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Proxies for HTTP message objects.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+class Proxies {
+
+ public static CloseableHttpResponse enhanceResponse(final HttpResponse original) {
+ Args.notNull(original, "HTTP response");
+ if (original instanceof CloseableHttpResponse) {
+ return (CloseableHttpResponse) original;
+ } else {
+ return (CloseableHttpResponse) Proxy.newProxyInstance(
+ ResponseProxyHandler.class.getClassLoader(),
+ new Class<?>[] { CloseableHttpResponse.class },
+ new ResponseProxyHandler(original));
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolCompliance.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolCompliance.java
new file mode 100644
index 000000000..ac7ab439c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolCompliance.java
@@ -0,0 +1,376 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.entity.AbstractHttpEntity;
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
+import ch.boye.httpclientandroidlib.message.BasicStatusLine;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * @since 4.1
+ */
+@Immutable
+class RequestProtocolCompliance {
+ private final boolean weakETagOnPutDeleteAllowed;
+
+ public RequestProtocolCompliance() {
+ super();
+ this.weakETagOnPutDeleteAllowed = false;
+ }
+
+ public RequestProtocolCompliance(final boolean weakETagOnPutDeleteAllowed) {
+ super();
+ this.weakETagOnPutDeleteAllowed = weakETagOnPutDeleteAllowed;
+ }
+
+ private static final List<String> disallowedWithNoCache =
+ Arrays.asList(HeaderConstants.CACHE_CONTROL_MIN_FRESH, HeaderConstants.CACHE_CONTROL_MAX_STALE, HeaderConstants.CACHE_CONTROL_MAX_AGE);
+
+ /**
+ * Test to see if the {@link HttpRequest} is HTTP1.1 compliant or not
+ * and if not, we can not continue.
+ *
+ * @param request the HttpRequest Object
+ * @return list of {@link RequestProtocolError}
+ */
+ public List<RequestProtocolError> requestIsFatallyNonCompliant(final HttpRequest request) {
+ final List<RequestProtocolError> theErrors = new ArrayList<RequestProtocolError>();
+
+ RequestProtocolError anError = requestHasWeakETagAndRange(request);
+ if (anError != null) {
+ theErrors.add(anError);
+ }
+
+ if (!weakETagOnPutDeleteAllowed) {
+ anError = requestHasWeekETagForPUTOrDELETEIfMatch(request);
+ if (anError != null) {
+ theErrors.add(anError);
+ }
+ }
+
+ anError = requestContainsNoCacheDirectiveWithFieldName(request);
+ if (anError != null) {
+ theErrors.add(anError);
+ }
+
+ return theErrors;
+ }
+
+ /**
+ * If the {@link HttpRequest} is non-compliant but 'fixable' we go ahead and
+ * fix the request here.
+ *
+ * @param request the request to check for compliance
+ * @throws ClientProtocolException when we have trouble making the request compliant
+ */
+ public void makeRequestCompliant(final HttpRequestWrapper request)
+ throws ClientProtocolException {
+
+ if (requestMustNotHaveEntity(request)) {
+ ((HttpEntityEnclosingRequest) request).setEntity(null);
+ }
+
+ verifyRequestWithExpectContinueFlagHas100continueHeader(request);
+ verifyOPTIONSRequestWithBodyHasContentType(request);
+ decrementOPTIONSMaxForwardsIfGreaterThen0(request);
+ stripOtherFreshnessDirectivesWithNoCache(request);
+
+ if (requestVersionIsTooLow(request)
+ || requestMinorVersionIsTooHighMajorVersionsMatch(request)) {
+ request.setProtocolVersion(HttpVersion.HTTP_1_1);
+ }
+ }
+
+ private void stripOtherFreshnessDirectivesWithNoCache(final HttpRequest request) {
+ final List<HeaderElement> outElts = new ArrayList<HeaderElement>();
+ boolean shouldStrip = false;
+ for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (!disallowedWithNoCache.contains(elt.getName())) {
+ outElts.add(elt);
+ }
+ if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) {
+ shouldStrip = true;
+ }
+ }
+ }
+ if (!shouldStrip) {
+ return;
+ }
+ request.removeHeaders(HeaderConstants.CACHE_CONTROL);
+ request.setHeader(HeaderConstants.CACHE_CONTROL, buildHeaderFromElements(outElts));
+ }
+
+ private String buildHeaderFromElements(final List<HeaderElement> outElts) {
+ final StringBuilder newHdr = new StringBuilder("");
+ boolean first = true;
+ for(final HeaderElement elt : outElts) {
+ if (!first) {
+ newHdr.append(",");
+ } else {
+ first = false;
+ }
+ newHdr.append(elt.toString());
+ }
+ return newHdr.toString();
+ }
+
+ private boolean requestMustNotHaveEntity(final HttpRequest request) {
+ return HeaderConstants.TRACE_METHOD.equals(request.getRequestLine().getMethod())
+ && request instanceof HttpEntityEnclosingRequest;
+ }
+
+ private void decrementOPTIONSMaxForwardsIfGreaterThen0(final HttpRequest request) {
+ if (!HeaderConstants.OPTIONS_METHOD.equals(request.getRequestLine().getMethod())) {
+ return;
+ }
+
+ final Header maxForwards = request.getFirstHeader(HeaderConstants.MAX_FORWARDS);
+ if (maxForwards == null) {
+ return;
+ }
+
+ request.removeHeaders(HeaderConstants.MAX_FORWARDS);
+ final int currentMaxForwards = Integer.parseInt(maxForwards.getValue());
+
+ request.setHeader(HeaderConstants.MAX_FORWARDS, Integer.toString(currentMaxForwards - 1));
+ }
+
+ private void verifyOPTIONSRequestWithBodyHasContentType(final HttpRequest request) {
+ if (!HeaderConstants.OPTIONS_METHOD.equals(request.getRequestLine().getMethod())) {
+ return;
+ }
+
+ if (!(request instanceof HttpEntityEnclosingRequest)) {
+ return;
+ }
+
+ addContentTypeHeaderIfMissing((HttpEntityEnclosingRequest) request);
+ }
+
+ private void addContentTypeHeaderIfMissing(final HttpEntityEnclosingRequest request) {
+ if (request.getEntity().getContentType() == null) {
+ ((AbstractHttpEntity) request.getEntity()).setContentType(
+ ContentType.APPLICATION_OCTET_STREAM.getMimeType());
+ }
+ }
+
+ private void verifyRequestWithExpectContinueFlagHas100continueHeader(final HttpRequest request) {
+ if (request instanceof HttpEntityEnclosingRequest) {
+
+ if (((HttpEntityEnclosingRequest) request).expectContinue()
+ && ((HttpEntityEnclosingRequest) request).getEntity() != null) {
+ add100ContinueHeaderIfMissing(request);
+ } else {
+ remove100ContinueHeaderIfExists(request);
+ }
+ } else {
+ remove100ContinueHeaderIfExists(request);
+ }
+ }
+
+ private void remove100ContinueHeaderIfExists(final HttpRequest request) {
+ boolean hasHeader = false;
+
+ final Header[] expectHeaders = request.getHeaders(HTTP.EXPECT_DIRECTIVE);
+ List<HeaderElement> expectElementsThatAreNot100Continue = new ArrayList<HeaderElement>();
+
+ for (final Header h : expectHeaders) {
+ for (final HeaderElement elt : h.getElements()) {
+ if (!(HTTP.EXPECT_CONTINUE.equalsIgnoreCase(elt.getName()))) {
+ expectElementsThatAreNot100Continue.add(elt);
+ } else {
+ hasHeader = true;
+ }
+ }
+
+ if (hasHeader) {
+ request.removeHeader(h);
+ for (final HeaderElement elt : expectElementsThatAreNot100Continue) {
+ final BasicHeader newHeader = new BasicHeader(HTTP.EXPECT_DIRECTIVE, elt.getName());
+ request.addHeader(newHeader);
+ }
+ return;
+ } else {
+ expectElementsThatAreNot100Continue = new ArrayList<HeaderElement>();
+ }
+ }
+ }
+
+ private void add100ContinueHeaderIfMissing(final HttpRequest request) {
+ boolean hasHeader = false;
+
+ for (final Header h : request.getHeaders(HTTP.EXPECT_DIRECTIVE)) {
+ for (final HeaderElement elt : h.getElements()) {
+ if (HTTP.EXPECT_CONTINUE.equalsIgnoreCase(elt.getName())) {
+ hasHeader = true;
+ }
+ }
+ }
+
+ if (!hasHeader) {
+ request.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
+ }
+ }
+
+ protected boolean requestMinorVersionIsTooHighMajorVersionsMatch(final HttpRequest request) {
+ final ProtocolVersion requestProtocol = request.getProtocolVersion();
+ if (requestProtocol.getMajor() != HttpVersion.HTTP_1_1.getMajor()) {
+ return false;
+ }
+
+ if (requestProtocol.getMinor() > HttpVersion.HTTP_1_1.getMinor()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean requestVersionIsTooLow(final HttpRequest request) {
+ return request.getProtocolVersion().compareToVersion(HttpVersion.HTTP_1_1) < 0;
+ }
+
+ /**
+ * Extract error information about the {@link HttpRequest} telling the 'caller'
+ * that a problem occured.
+ *
+ * @param errorCheck What type of error should I get
+ * @return The {@link HttpResponse} that is the error generated
+ */
+ public HttpResponse getErrorForRequest(final RequestProtocolError errorCheck) {
+ switch (errorCheck) {
+ case BODY_BUT_NO_LENGTH_ERROR:
+ return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_LENGTH_REQUIRED, ""));
+
+ case WEAK_ETAG_AND_RANGE_ERROR:
+ return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_BAD_REQUEST, "Weak eTag not compatible with byte range"));
+
+ case WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR:
+ return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_BAD_REQUEST,
+ "Weak eTag not compatible with PUT or DELETE requests"));
+
+ case NO_CACHE_DIRECTIVE_WITH_FIELD_NAME:
+ return new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_BAD_REQUEST,
+ "No-Cache directive MUST NOT include a field name"));
+
+ default:
+ throw new IllegalStateException(
+ "The request was compliant, therefore no error can be generated for it.");
+
+ }
+ }
+
+ private RequestProtocolError requestHasWeakETagAndRange(final HttpRequest request) {
+ // TODO: Should these be looking at all the headers marked as Range?
+ final String method = request.getRequestLine().getMethod();
+ if (!(HeaderConstants.GET_METHOD.equals(method))) {
+ return null;
+ }
+
+ final Header range = request.getFirstHeader(HeaderConstants.RANGE);
+ if (range == null) {
+ return null;
+ }
+
+ final Header ifRange = request.getFirstHeader(HeaderConstants.IF_RANGE);
+ if (ifRange == null) {
+ return null;
+ }
+
+ final String val = ifRange.getValue();
+ if (val.startsWith("W/")) {
+ return RequestProtocolError.WEAK_ETAG_AND_RANGE_ERROR;
+ }
+
+ return null;
+ }
+
+ private RequestProtocolError requestHasWeekETagForPUTOrDELETEIfMatch(final HttpRequest request) {
+ // TODO: Should these be looking at all the headers marked as If-Match/If-None-Match?
+
+ final String method = request.getRequestLine().getMethod();
+ if (!(HeaderConstants.PUT_METHOD.equals(method) || HeaderConstants.DELETE_METHOD
+ .equals(method))) {
+ return null;
+ }
+
+ final Header ifMatch = request.getFirstHeader(HeaderConstants.IF_MATCH);
+ if (ifMatch != null) {
+ final String val = ifMatch.getValue();
+ if (val.startsWith("W/")) {
+ return RequestProtocolError.WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR;
+ }
+ } else {
+ final Header ifNoneMatch = request.getFirstHeader(HeaderConstants.IF_NONE_MATCH);
+ if (ifNoneMatch == null) {
+ return null;
+ }
+
+ final String val2 = ifNoneMatch.getValue();
+ if (val2.startsWith("W/")) {
+ return RequestProtocolError.WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR;
+ }
+ }
+
+ return null;
+ }
+
+ private RequestProtocolError requestContainsNoCacheDirectiveWithFieldName(final HttpRequest request) {
+ for(final Header h : request.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for(final HeaderElement elt : h.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(elt.getName())
+ && elt.getValue() != null) {
+ return RequestProtocolError.NO_CACHE_DIRECTIVE_WITH_FIELD_NAME;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolError.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolError.java
new file mode 100644
index 000000000..1cc5668c7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/RequestProtocolError.java
@@ -0,0 +1,40 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+/**
+ * @since 4.1
+ */
+enum RequestProtocolError {
+
+ UNKNOWN,
+ BODY_BUT_NO_LENGTH_ERROR,
+ WEAK_ETAG_ON_PUTDELETE_METHOD_ERROR,
+ WEAK_ETAG_AND_RANGE_ERROR,
+ NO_CACHE_DIRECTIVE_WITH_FIELD_NAME
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResourceReference.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResourceReference.java
new file mode 100644
index 000000000..5e3f368f1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResourceReference.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.util.Args;
+
+@Immutable
+class ResourceReference extends PhantomReference<HttpCacheEntry> {
+
+ private final Resource resource;
+
+ public ResourceReference(final HttpCacheEntry entry, final ReferenceQueue<HttpCacheEntry> q) {
+ super(entry, q);
+ Args.notNull(entry.getResource(), "Resource");
+ this.resource = entry.getResource();
+ }
+
+ public Resource getResource() {
+ return this.resource;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.resource.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return this.resource.equals(obj);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseCachingPolicy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseCachingPolicy.java
new file mode 100644
index 000000000..abadb88d4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseCachingPolicy.java
@@ -0,0 +1,311 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * Determines if an HttpResponse can be cached.
+ *
+ * @since 4.1
+ */
+@Immutable
+class ResponseCachingPolicy {
+
+ private static final String[] AUTH_CACHEABLE_PARAMS = {
+ "s-maxage", HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE, HeaderConstants.PUBLIC
+ };
+ private final long maxObjectSizeBytes;
+ private final boolean sharedCache;
+ private final boolean neverCache1_0ResponsesWithQueryString;
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+ private static final Set<Integer> cacheableStatuses =
+ new HashSet<Integer>(Arrays.asList(HttpStatus.SC_OK,
+ HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION,
+ HttpStatus.SC_MULTIPLE_CHOICES,
+ HttpStatus.SC_MOVED_PERMANENTLY,
+ HttpStatus.SC_GONE));
+ private final Set<Integer> uncacheableStatuses;
+ /**
+ * Define a cache policy that limits the size of things that should be stored
+ * in the cache to a maximum of {@link HttpResponse} bytes in size.
+ *
+ * @param maxObjectSizeBytes the size to limit items into the cache
+ * @param sharedCache whether to behave as a shared cache (true) or a
+ * non-shared/private cache (false)
+ * @param neverCache1_0ResponsesWithQueryString true to never cache HTTP 1.0 responses with a query string, false
+ * to cache if explicit cache headers are found.
+ * @param allow303Caching if this policy is permitted to cache 303 response
+ */
+ public ResponseCachingPolicy(final long maxObjectSizeBytes,
+ final boolean sharedCache,
+ final boolean neverCache1_0ResponsesWithQueryString,
+ final boolean allow303Caching) {
+ this.maxObjectSizeBytes = maxObjectSizeBytes;
+ this.sharedCache = sharedCache;
+ this.neverCache1_0ResponsesWithQueryString = neverCache1_0ResponsesWithQueryString;
+ if (allow303Caching) {
+ uncacheableStatuses = new HashSet<Integer>(
+ Arrays.asList(HttpStatus.SC_PARTIAL_CONTENT));
+ } else {
+ uncacheableStatuses = new HashSet<Integer>(Arrays.asList(
+ HttpStatus.SC_PARTIAL_CONTENT, HttpStatus.SC_SEE_OTHER));
+ }
+ }
+
+ /**
+ * Determines if an HttpResponse can be cached.
+ *
+ * @param httpMethod What type of request was this, a GET, PUT, other?
+ * @param response The origin response
+ * @return <code>true</code> if response is cacheable
+ */
+ public boolean isResponseCacheable(final String httpMethod, final HttpResponse response) {
+ boolean cacheable = false;
+
+ if (!HeaderConstants.GET_METHOD.equals(httpMethod)) {
+ log.debug("Response was not cacheable.");
+ return false;
+ }
+
+ final int status = response.getStatusLine().getStatusCode();
+ if (cacheableStatuses.contains(status)) {
+ // these response codes MAY be cached
+ cacheable = true;
+ } else if (uncacheableStatuses.contains(status)) {
+ return false;
+ } else if (unknownStatusCode(status)) {
+ // a response with an unknown status code MUST NOT be
+ // cached
+ return false;
+ }
+
+ final Header contentLength = response.getFirstHeader(HTTP.CONTENT_LEN);
+ if (contentLength != null) {
+ final int contentLengthValue = Integer.parseInt(contentLength.getValue());
+ if (contentLengthValue > this.maxObjectSizeBytes) {
+ return false;
+ }
+ }
+
+ final Header[] ageHeaders = response.getHeaders(HeaderConstants.AGE);
+
+ if (ageHeaders.length > 1) {
+ return false;
+ }
+
+ final Header[] expiresHeaders = response.getHeaders(HeaderConstants.EXPIRES);
+
+ if (expiresHeaders.length > 1) {
+ return false;
+ }
+
+ final Header[] dateHeaders = response.getHeaders(HTTP.DATE_HEADER);
+
+ if (dateHeaders.length != 1) {
+ return false;
+ }
+
+ final Date date = DateUtils.parseDate(dateHeaders[0].getValue());
+ if (date == null) {
+ return false;
+ }
+
+ for (final Header varyHdr : response.getHeaders(HeaderConstants.VARY)) {
+ for (final HeaderElement elem : varyHdr.getElements()) {
+ if ("*".equals(elem.getName())) {
+ return false;
+ }
+ }
+ }
+
+ if (isExplicitlyNonCacheable(response)) {
+ return false;
+ }
+
+ return (cacheable || isExplicitlyCacheable(response));
+ }
+
+ private boolean unknownStatusCode(final int status) {
+ if (status >= 100 && status <= 101) {
+ return false;
+ }
+ if (status >= 200 && status <= 206) {
+ return false;
+ }
+ if (status >= 300 && status <= 307) {
+ return false;
+ }
+ if (status >= 400 && status <= 417) {
+ return false;
+ }
+ if (status >= 500 && status <= 505) {
+ return false;
+ }
+ return true;
+ }
+
+ protected boolean isExplicitlyNonCacheable(final HttpResponse response) {
+ final Header[] cacheControlHeaders = response.getHeaders(HeaderConstants.CACHE_CONTROL);
+ for (final Header header : cacheControlHeaders) {
+ for (final HeaderElement elem : header.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elem.getName())
+ || HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elem.getName())
+ || (sharedCache && HeaderConstants.PRIVATE.equals(elem.getName()))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean hasCacheControlParameterFrom(final HttpMessage msg, final String[] params) {
+ final Header[] cacheControlHeaders = msg.getHeaders(HeaderConstants.CACHE_CONTROL);
+ for (final Header header : cacheControlHeaders) {
+ for (final HeaderElement elem : header.getElements()) {
+ for (final String param : params) {
+ if (param.equalsIgnoreCase(elem.getName())) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean isExplicitlyCacheable(final HttpResponse response) {
+ if (response.getFirstHeader(HeaderConstants.EXPIRES) != null) {
+ return true;
+ }
+ final String[] cacheableParams = { HeaderConstants.CACHE_CONTROL_MAX_AGE, "s-maxage",
+ HeaderConstants.CACHE_CONTROL_MUST_REVALIDATE,
+ HeaderConstants.CACHE_CONTROL_PROXY_REVALIDATE,
+ HeaderConstants.PUBLIC
+ };
+ return hasCacheControlParameterFrom(response, cacheableParams);
+ }
+
+ /**
+ * Determine if the {@link HttpResponse} gotten from the origin is a
+ * cacheable response.
+ *
+ * @param request the {@link HttpRequest} that generated an origin hit
+ * @param response the {@link HttpResponse} from the origin
+ * @return <code>true</code> if response is cacheable
+ */
+ public boolean isResponseCacheable(final HttpRequest request, final HttpResponse response) {
+ if (requestProtocolGreaterThanAccepted(request)) {
+ log.debug("Response was not cacheable.");
+ return false;
+ }
+
+ final String[] uncacheableRequestDirectives = { HeaderConstants.CACHE_CONTROL_NO_STORE };
+ if (hasCacheControlParameterFrom(request,uncacheableRequestDirectives)) {
+ return false;
+ }
+
+ if (request.getRequestLine().getUri().contains("?")) {
+ if (neverCache1_0ResponsesWithQueryString && from1_0Origin(response)) {
+ log.debug("Response was not cacheable as it had a query string.");
+ return false;
+ } else if (!isExplicitlyCacheable(response)) {
+ log.debug("Response was not cacheable as it is missing explicit caching headers.");
+ return false;
+ }
+ }
+
+ if (expiresHeaderLessOrEqualToDateHeaderAndNoCacheControl(response)) {
+ return false;
+ }
+
+ if (sharedCache) {
+ final Header[] authNHeaders = request.getHeaders(HeaderConstants.AUTHORIZATION);
+ if (authNHeaders != null && authNHeaders.length > 0
+ && !hasCacheControlParameterFrom(response, AUTH_CACHEABLE_PARAMS)) {
+ return false;
+ }
+ }
+
+ final String method = request.getRequestLine().getMethod();
+ return isResponseCacheable(method, response);
+ }
+
+ private boolean expiresHeaderLessOrEqualToDateHeaderAndNoCacheControl(
+ final HttpResponse response) {
+ if (response.getFirstHeader(HeaderConstants.CACHE_CONTROL) != null) {
+ return false;
+ }
+ final Header expiresHdr = response.getFirstHeader(HeaderConstants.EXPIRES);
+ final Header dateHdr = response.getFirstHeader(HTTP.DATE_HEADER);
+ if (expiresHdr == null || dateHdr == null) {
+ return false;
+ }
+ final Date expires = DateUtils.parseDate(expiresHdr.getValue());
+ final Date date = DateUtils.parseDate(dateHdr.getValue());
+ if (expires == null || date == null) {
+ return false;
+ }
+ return expires.equals(date) || expires.before(date);
+ }
+
+ private boolean from1_0Origin(final HttpResponse response) {
+ final Header via = response.getFirstHeader(HeaderConstants.VIA);
+ if (via != null) {
+ for(final HeaderElement elt : via.getElements()) {
+ final String proto = elt.toString().split("\\s")[0];
+ if (proto.contains("/")) {
+ return proto.equals("HTTP/1.0");
+ } else {
+ return proto.equals("1.0");
+ }
+ }
+ }
+ return HttpVersion.HTTP_1_0.equals(response.getProtocolVersion());
+ }
+
+ private boolean requestProtocolGreaterThanAccepted(final HttpRequest req) {
+ return req.getProtocolVersion().compareToVersion(HttpVersion.HTTP_1_1) > 0;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProtocolCompliance.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProtocolCompliance.java
new file mode 100644
index 000000000..7f5ebb483
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProtocolCompliance.java
@@ -0,0 +1,251 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.cache.HeaderConstants;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * @since 4.1
+ */
+@Immutable
+class ResponseProtocolCompliance {
+
+ private static final String UNEXPECTED_100_CONTINUE = "The incoming request did not contain a "
+ + "100-continue header, but the response was a Status 100, continue.";
+ private static final String UNEXPECTED_PARTIAL_CONTENT = "partial content was returned for a request that did not ask for it";
+
+ /**
+ * When we get a response from a down stream server (Origin Server)
+ * we attempt to see if it is HTTP 1.1 Compliant and if not, attempt to
+ * make it so.
+ *
+ * @param request The {@link HttpRequest} that generated an origin hit and response
+ * @param response The {@link HttpResponse} from the origin server
+ * @throws IOException Bad things happened
+ */
+ public void ensureProtocolCompliance(final HttpRequestWrapper request, final HttpResponse response)
+ throws IOException {
+ if (backendResponseMustNotHaveBody(request, response)) {
+ consumeBody(response);
+ response.setEntity(null);
+ }
+
+ requestDidNotExpect100ContinueButResponseIsOne(request, response);
+
+ transferEncodingIsNotReturnedTo1_0Client(request, response);
+
+ ensurePartialContentIsNotSentToAClientThatDidNotRequestIt(request, response);
+
+ ensure200ForOPTIONSRequestWithNoBodyHasContentLengthZero(request, response);
+
+ ensure206ContainsDateHeader(response);
+
+ ensure304DoesNotContainExtraEntityHeaders(response);
+
+ identityIsNotUsedInContentEncoding(response);
+
+ warningsWithNonMatchingWarnDatesAreRemoved(response);
+ }
+
+ private void consumeBody(final HttpResponse response) throws IOException {
+ final HttpEntity body = response.getEntity();
+ if (body != null) {
+ IOUtils.consume(body);
+ }
+ }
+
+ private void warningsWithNonMatchingWarnDatesAreRemoved(
+ final HttpResponse response) {
+ final Date responseDate = DateUtils.parseDate(response.getFirstHeader(HTTP.DATE_HEADER).getValue());
+ if (responseDate == null) {
+ return;
+ }
+
+ final Header[] warningHeaders = response.getHeaders(HeaderConstants.WARNING);
+
+ if (warningHeaders == null || warningHeaders.length == 0) {
+ return;
+ }
+
+ final List<Header> newWarningHeaders = new ArrayList<Header>();
+ boolean modified = false;
+ for(final Header h : warningHeaders) {
+ for(final WarningValue wv : WarningValue.getWarningValues(h)) {
+ final Date warnDate = wv.getWarnDate();
+ if (warnDate == null || warnDate.equals(responseDate)) {
+ newWarningHeaders.add(new BasicHeader(HeaderConstants.WARNING,wv.toString()));
+ } else {
+ modified = true;
+ }
+ }
+ }
+ if (modified) {
+ response.removeHeaders(HeaderConstants.WARNING);
+ for(final Header h : newWarningHeaders) {
+ response.addHeader(h);
+ }
+ }
+ }
+
+ private void identityIsNotUsedInContentEncoding(final HttpResponse response) {
+ final Header[] hdrs = response.getHeaders(HTTP.CONTENT_ENCODING);
+ if (hdrs == null || hdrs.length == 0) {
+ return;
+ }
+ final List<Header> newHeaders = new ArrayList<Header>();
+ boolean modified = false;
+ for (final Header h : hdrs) {
+ final StringBuilder buf = new StringBuilder();
+ boolean first = true;
+ for (final HeaderElement elt : h.getElements()) {
+ if ("identity".equalsIgnoreCase(elt.getName())) {
+ modified = true;
+ } else {
+ if (!first) {
+ buf.append(",");
+ }
+ buf.append(elt.toString());
+ first = false;
+ }
+ }
+ final String newHeaderValue = buf.toString();
+ if (!"".equals(newHeaderValue)) {
+ newHeaders.add(new BasicHeader(HTTP.CONTENT_ENCODING, newHeaderValue));
+ }
+ }
+ if (!modified) {
+ return;
+ }
+ response.removeHeaders(HTTP.CONTENT_ENCODING);
+ for (final Header h : newHeaders) {
+ response.addHeader(h);
+ }
+ }
+
+ private void ensure206ContainsDateHeader(final HttpResponse response) {
+ if (response.getFirstHeader(HTTP.DATE_HEADER) == null) {
+ response.addHeader(HTTP.DATE_HEADER, DateUtils.formatDate(new Date()));
+ }
+
+ }
+
+ private void ensurePartialContentIsNotSentToAClientThatDidNotRequestIt(final HttpRequest request,
+ final HttpResponse response) throws IOException {
+ if (request.getFirstHeader(HeaderConstants.RANGE) != null
+ || response.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT) {
+ return;
+ }
+
+ consumeBody(response);
+ throw new ClientProtocolException(UNEXPECTED_PARTIAL_CONTENT);
+ }
+
+ private void ensure200ForOPTIONSRequestWithNoBodyHasContentLengthZero(final HttpRequest request,
+ final HttpResponse response) {
+ if (!request.getRequestLine().getMethod().equalsIgnoreCase(HeaderConstants.OPTIONS_METHOD)) {
+ return;
+ }
+
+ if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+ return;
+ }
+
+ if (response.getFirstHeader(HTTP.CONTENT_LEN) == null) {
+ response.addHeader(HTTP.CONTENT_LEN, "0");
+ }
+ }
+
+ private void ensure304DoesNotContainExtraEntityHeaders(final HttpResponse response) {
+ final String[] disallowedEntityHeaders = { HeaderConstants.ALLOW, HTTP.CONTENT_ENCODING,
+ "Content-Language", HTTP.CONTENT_LEN, "Content-MD5",
+ "Content-Range", HTTP.CONTENT_TYPE, HeaderConstants.LAST_MODIFIED
+ };
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+ for(final String hdr : disallowedEntityHeaders) {
+ response.removeHeaders(hdr);
+ }
+ }
+ }
+
+ private boolean backendResponseMustNotHaveBody(final HttpRequest request, final HttpResponse backendResponse) {
+ return HeaderConstants.HEAD_METHOD.equals(request.getRequestLine().getMethod())
+ || backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT
+ || backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_RESET_CONTENT
+ || backendResponse.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED;
+ }
+
+ private void requestDidNotExpect100ContinueButResponseIsOne(final HttpRequestWrapper request,
+ final HttpResponse response) throws IOException {
+ if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CONTINUE) {
+ return;
+ }
+
+ final HttpRequest originalRequest = request.getOriginal();
+ if (originalRequest instanceof HttpEntityEnclosingRequest) {
+ if (((HttpEntityEnclosingRequest)originalRequest).expectContinue()) {
+ return;
+ }
+ }
+ consumeBody(response);
+ throw new ClientProtocolException(UNEXPECTED_100_CONTINUE);
+ }
+
+ private void transferEncodingIsNotReturnedTo1_0Client(final HttpRequestWrapper request,
+ final HttpResponse response) {
+ final HttpRequest originalRequest = request.getOriginal();
+ if (originalRequest.getProtocolVersion().compareToVersion(HttpVersion.HTTP_1_1) >= 0) {
+ return;
+ }
+
+ removeResponseTransferEncoding(response);
+ }
+
+ private void removeResponseTransferEncoding(final HttpResponse response) {
+ response.removeHeaders("TE");
+ response.removeHeaders(HTTP.TRANSFER_ENCODING);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProxyHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProxyHandler.java
new file mode 100644
index 000000000..a541b2778
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/ResponseProxyHandler.java
@@ -0,0 +1,88 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * A proxy class that can enhance an arbitrary {@link HttpResponse} with
+ * {@link Closeable#close()} method.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+class ResponseProxyHandler implements InvocationHandler {
+
+ private static final Method CLOSE_METHOD;
+
+ static {
+ try {
+ CLOSE_METHOD = Closeable.class.getMethod("close");
+ } catch (final NoSuchMethodException ex) {
+ throw new Error(ex);
+ }
+ }
+
+ private final HttpResponse original;
+
+ ResponseProxyHandler(final HttpResponse original) {
+ super();
+ this.original = original;
+ }
+
+ public void close() throws IOException {
+ IOUtils.consume(original.getEntity());
+ }
+
+ public Object invoke(
+ final Object proxy, final Method method, final Object[] args) throws Throwable {
+ if (method.equals(CLOSE_METHOD)) {
+ close();
+ return null;
+ } else {
+ try {
+ return method.invoke(this.original, args);
+ } catch (final InvocationTargetException ex) {
+ final Throwable cause = ex.getCause();
+ if (cause != null) {
+ throw cause;
+ } else {
+ throw ex;
+ }
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SchedulingStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SchedulingStrategy.java
new file mode 100644
index 000000000..0940fbc83
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SchedulingStrategy.java
@@ -0,0 +1,45 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.Closeable;
+
+/**
+ * Specifies when revalidation requests are scheduled.
+ *
+ * @since 4.3
+ */
+public interface SchedulingStrategy extends Closeable
+{
+ /**
+ * Schedule an {@link AsynchronousValidationRequest} to be executed.
+ *
+ * @param revalidationRequest the request to be executed; not <code>null</code>
+ * @throws java.util.concurrent.RejectedExecutionException if the request could not be scheduled for execution
+ */
+ void schedule(AsynchronousValidationRequest revalidationRequest);
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SizeLimitedResponseReader.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SizeLimitedResponseReader.java
new file mode 100644
index 000000000..4c36ebb48
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/SizeLimitedResponseReader.java
@@ -0,0 +1,150 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Proxy;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.cache.InputLimit;
+import ch.boye.httpclientandroidlib.client.cache.Resource;
+import ch.boye.httpclientandroidlib.client.cache.ResourceFactory;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
+
+/**
+ * @since 4.1
+ */
+@NotThreadSafe
+class SizeLimitedResponseReader {
+
+ private final ResourceFactory resourceFactory;
+ private final long maxResponseSizeBytes;
+ private final HttpRequest request;
+ private final CloseableHttpResponse response;
+
+ private InputStream instream;
+ private InputLimit limit;
+ private Resource resource;
+ private boolean consumed;
+
+ /**
+ * Create an {@link HttpResponse} that is limited in size, this allows for checking
+ * the size of objects that will be stored in the cache.
+ */
+ public SizeLimitedResponseReader(
+ final ResourceFactory resourceFactory,
+ final long maxResponseSizeBytes,
+ final HttpRequest request,
+ final CloseableHttpResponse response) {
+ super();
+ this.resourceFactory = resourceFactory;
+ this.maxResponseSizeBytes = maxResponseSizeBytes;
+ this.request = request;
+ this.response = response;
+ }
+
+ protected void readResponse() throws IOException {
+ if (!consumed) {
+ doConsume();
+ }
+ }
+
+ private void ensureNotConsumed() {
+ if (consumed) {
+ throw new IllegalStateException("Response has already been consumed");
+ }
+ }
+
+ private void ensureConsumed() {
+ if (!consumed) {
+ throw new IllegalStateException("Response has not been consumed");
+ }
+ }
+
+ private void doConsume() throws IOException {
+ ensureNotConsumed();
+ consumed = true;
+
+ limit = new InputLimit(maxResponseSizeBytes);
+
+ final HttpEntity entity = response.getEntity();
+ if (entity == null) {
+ return;
+ }
+ final String uri = request.getRequestLine().getUri();
+ instream = entity.getContent();
+ try {
+ resource = resourceFactory.generate(uri, instream, limit);
+ } finally {
+ if (!limit.isReached()) {
+ instream.close();
+ }
+ }
+ }
+
+ boolean isLimitReached() {
+ ensureConsumed();
+ return limit.isReached();
+ }
+
+ Resource getResource() {
+ ensureConsumed();
+ return resource;
+ }
+
+ CloseableHttpResponse getReconstructedResponse() throws IOException {
+ ensureConsumed();
+ final HttpResponse reconstructed = new BasicHttpResponse(response.getStatusLine());
+ reconstructed.setHeaders(response.getAllHeaders());
+
+ final CombinedEntity combinedEntity = new CombinedEntity(resource, instream);
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ combinedEntity.setContentType(entity.getContentType());
+ combinedEntity.setContentEncoding(entity.getContentEncoding());
+ combinedEntity.setChunked(entity.isChunked());
+ }
+ reconstructed.setEntity(combinedEntity);
+ return (CloseableHttpResponse) Proxy.newProxyInstance(
+ ResponseProxyHandler.class.getClassLoader(),
+ new Class<?>[] { CloseableHttpResponse.class },
+ new ResponseProxyHandler(reconstructed) {
+
+ @Override
+ public void close() throws IOException {
+ response.close();
+ }
+
+ });
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Variant.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Variant.java
new file mode 100644
index 000000000..f631b0211
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/Variant.java
@@ -0,0 +1,55 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import ch.boye.httpclientandroidlib.client.cache.HttpCacheEntry;
+
+/** Records a set of information describing a cached variant. */
+class Variant {
+
+ private final String variantKey;
+ private final String cacheKey;
+ private final HttpCacheEntry entry;
+
+ public Variant(final String variantKey, final String cacheKey, final HttpCacheEntry entry) {
+ this.variantKey = variantKey;
+ this.cacheKey = cacheKey;
+ this.entry = entry;
+ }
+
+ public String getVariantKey() {
+ return variantKey;
+ }
+
+ public String getCacheKey() {
+ return cacheKey;
+ }
+
+ public HttpCacheEntry getEntry() {
+ return entry;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/WarningValue.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/WarningValue.java
new file mode 100644
index 000000000..a3c2ce67d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/WarningValue.java
@@ -0,0 +1,370 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.client.cache;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+
+/** This class provides for parsing and understanding Warning headers. As
+ * the Warning header can be multi-valued, but the values can contain
+ * separators like commas inside quoted strings, we cannot use the regular
+ * {@link Header#getElements()} call to access the values.
+ */
+class WarningValue {
+
+ private int offs;
+ private int init_offs;
+ private final String src;
+ private int warnCode;
+ private String warnAgent;
+ private String warnText;
+ private Date warnDate;
+
+ WarningValue(final String s) {
+ this(s, 0);
+ }
+
+ WarningValue(final String s, final int offs) {
+ this.offs = this.init_offs = offs;
+ this.src = s;
+ consumeWarnValue();
+ }
+
+ /** Returns an array of the parseable warning values contained
+ * in the given header value, which is assumed to be a
+ * Warning header. Improperly formatted warning values will be
+ * skipped, in keeping with the philosophy of "ignore what you
+ * cannot understand."
+ * @param h Warning {@link Header} to parse
+ * @return array of <code>WarnValue</code> objects
+ */
+ public static WarningValue[] getWarningValues(final Header h) {
+ final List<WarningValue> out = new ArrayList<WarningValue>();
+ final String src = h.getValue();
+ int offs = 0;
+ while(offs < src.length()) {
+ try {
+ final WarningValue wv = new WarningValue(src, offs);
+ out.add(wv);
+ offs = wv.offs;
+ } catch (final IllegalArgumentException e) {
+ final int nextComma = src.indexOf(',', offs);
+ if (nextComma == -1) {
+ break;
+ }
+ offs = nextComma + 1;
+ }
+ }
+ final WarningValue[] wvs = {};
+ return out.toArray(wvs);
+ }
+
+ /*
+ * LWS = [CRLF] 1*( SP | HT )
+ * CRLF = CR LF
+ */
+ protected void consumeLinearWhitespace() {
+ while(offs < src.length()) {
+ switch(src.charAt(offs)) {
+ case '\r':
+ if (offs+2 >= src.length()
+ || src.charAt(offs+1) != '\n'
+ || (src.charAt(offs+2) != ' '
+ && src.charAt(offs+2) != '\t')) {
+ return;
+ }
+ offs += 2;
+ break;
+ case ' ':
+ case '\t':
+ break;
+ default:
+ return;
+ }
+ offs++;
+ }
+ }
+
+ /*
+ * CHAR = <any US-ASCII character (octets 0 - 127)>
+ */
+ private boolean isChar(final char c) {
+ final int i = c;
+ return (i >= 0 && i <= 127);
+ }
+
+ /*
+ * CTL = <any US-ASCII control character
+ (octets 0 - 31) and DEL (127)>
+ */
+ private boolean isControl(final char c) {
+ final int i = c;
+ return (i == 127 || (i >=0 && i <= 31));
+ }
+
+ /*
+ * separators = "(" | ")" | "<" | ">" | "@"
+ * | "," | ";" | ":" | "\" | <">
+ * | "/" | "[" | "]" | "?" | "="
+ * | "{" | "}" | SP | HT
+ */
+ private boolean isSeparator(final char c) {
+ return (c == '(' || c == ')' || c == '<' || c == '>'
+ || c == '@' || c == ',' || c == ';' || c == ':'
+ || c == '\\' || c == '\"' || c == '/'
+ || c == '[' || c == ']' || c == '?' || c == '='
+ || c == '{' || c == '}' || c == ' ' || c == '\t');
+ }
+
+ /*
+ * token = 1*<any CHAR except CTLs or separators>
+ */
+ protected void consumeToken() {
+ if (!isTokenChar(src.charAt(offs))) {
+ parseError();
+ }
+ while(offs < src.length()) {
+ if (!isTokenChar(src.charAt(offs))) {
+ break;
+ }
+ offs++;
+ }
+ }
+
+ private boolean isTokenChar(final char c) {
+ return (isChar(c) && !isControl(c) && !isSeparator(c));
+ }
+
+ private static final String TOPLABEL = "\\p{Alpha}([\\p{Alnum}-]*\\p{Alnum})?";
+ private static final String DOMAINLABEL = "\\p{Alnum}([\\p{Alnum}-]*\\p{Alnum})?";
+ private static final String HOSTNAME = "(" + DOMAINLABEL + "\\.)*" + TOPLABEL + "\\.?";
+ private static final String IPV4ADDRESS = "\\d+\\.\\d+\\.\\d+\\.\\d+";
+ private static final String HOST = "(" + HOSTNAME + ")|(" + IPV4ADDRESS + ")";
+ private static final String PORT = "\\d*";
+ private static final String HOSTPORT = "(" + HOST + ")(\\:" + PORT + ")?";
+ private static final Pattern HOSTPORT_PATTERN = Pattern.compile(HOSTPORT);
+
+ protected void consumeHostPort() {
+ final Matcher m = HOSTPORT_PATTERN.matcher(src.substring(offs));
+ if (!m.find()) {
+ parseError();
+ }
+ if (m.start() != 0) {
+ parseError();
+ }
+ offs += m.end();
+ }
+
+
+ /*
+ * warn-agent = ( host [ ":" port ] ) | pseudonym
+ * pseudonym = token
+ */
+ protected void consumeWarnAgent() {
+ final int curr_offs = offs;
+ try {
+ consumeHostPort();
+ warnAgent = src.substring(curr_offs, offs);
+ consumeCharacter(' ');
+ return;
+ } catch (final IllegalArgumentException e) {
+ offs = curr_offs;
+ }
+ consumeToken();
+ warnAgent = src.substring(curr_offs, offs);
+ consumeCharacter(' ');
+ }
+
+ /*
+ * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
+ * qdtext = <any TEXT except <">>
+ */
+ protected void consumeQuotedString() {
+ if (src.charAt(offs) != '\"') {
+ parseError();
+ }
+ offs++;
+ boolean foundEnd = false;
+ while(offs < src.length() && !foundEnd) {
+ final char c = src.charAt(offs);
+ if (offs + 1 < src.length() && c == '\\'
+ && isChar(src.charAt(offs+1))) {
+ offs += 2; // consume quoted-pair
+ } else if (c == '\"') {
+ foundEnd = true;
+ offs++;
+ } else if (c != '\"' && !isControl(c)) {
+ offs++;
+ } else {
+ parseError();
+ }
+ }
+ if (!foundEnd) {
+ parseError();
+ }
+ }
+
+ /*
+ * warn-text = quoted-string
+ */
+ protected void consumeWarnText() {
+ final int curr = offs;
+ consumeQuotedString();
+ warnText = src.substring(curr, offs);
+ }
+
+ private static final String MONTH = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec";
+ private static final String WEEKDAY = "Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday";
+ private static final String WKDAY = "Mon|Tue|Wed|Thu|Fri|Sat|Sun";
+ private static final String TIME = "\\d{2}:\\d{2}:\\d{2}";
+ private static final String DATE3 = "(" + MONTH + ") ( |\\d)\\d";
+ private static final String DATE2 = "\\d{2}-(" + MONTH + ")-\\d{2}";
+ private static final String DATE1 = "\\d{2} (" + MONTH + ") \\d{4}";
+ private static final String ASCTIME_DATE = "(" + WKDAY + ") (" + DATE3 + ") (" + TIME + ") \\d{4}";
+ private static final String RFC850_DATE = "(" + WEEKDAY + "), (" + DATE2 + ") (" + TIME + ") GMT";
+ private static final String RFC1123_DATE = "(" + WKDAY + "), (" + DATE1 + ") (" + TIME + ") GMT";
+ private static final String HTTP_DATE = "(" + RFC1123_DATE + ")|(" + RFC850_DATE + ")|(" + ASCTIME_DATE + ")";
+ private static final String WARN_DATE = "\"(" + HTTP_DATE + ")\"";
+ private static final Pattern WARN_DATE_PATTERN = Pattern.compile(WARN_DATE);
+
+ /*
+ * warn-date = <"> HTTP-date <">
+ */
+ protected void consumeWarnDate() {
+ final int curr = offs;
+ final Matcher m = WARN_DATE_PATTERN.matcher(src.substring(offs));
+ if (!m.lookingAt()) {
+ parseError();
+ }
+ offs += m.end();
+ warnDate = DateUtils.parseDate(src.substring(curr+1,offs-1));
+ }
+
+ /*
+ * warning-value = warn-code SP warn-agent SP warn-text [SP warn-date]
+ */
+ protected void consumeWarnValue() {
+ consumeLinearWhitespace();
+ consumeWarnCode();
+ consumeWarnAgent();
+ consumeWarnText();
+ if (offs + 1 < src.length() && src.charAt(offs) == ' ' && src.charAt(offs+1) == '\"') {
+ consumeCharacter(' ');
+ consumeWarnDate();
+ }
+ consumeLinearWhitespace();
+ if (offs != src.length()) {
+ consumeCharacter(',');
+ }
+ }
+
+ protected void consumeCharacter(final char c) {
+ if (offs + 1 > src.length()
+ || c != src.charAt(offs)) {
+ parseError();
+ }
+ offs++;
+ }
+
+ /*
+ * warn-code = 3DIGIT
+ */
+ protected void consumeWarnCode() {
+ if (offs + 4 > src.length()
+ || !Character.isDigit(src.charAt(offs))
+ || !Character.isDigit(src.charAt(offs + 1))
+ || !Character.isDigit(src.charAt(offs + 2))
+ || src.charAt(offs + 3) != ' ') {
+ parseError();
+ }
+ warnCode = Integer.parseInt(src.substring(offs,offs+3));
+ offs += 4;
+ }
+
+ private void parseError() {
+ final String s = src.substring(init_offs);
+ throw new IllegalArgumentException("Bad warn code \"" + s + "\"");
+ }
+
+ /** Returns the 3-digit code associated with this warning.
+ * @return <code>int</code>
+ */
+ public int getWarnCode() { return warnCode; }
+
+ /** Returns the "warn-agent" string associated with this warning,
+ * which is either the name or pseudonym of the server that added
+ * this particular Warning header.
+ * @return {@link String}
+ */
+ public String getWarnAgent() { return warnAgent; }
+
+ /** Returns the human-readable warning text for this warning. Note
+ * that the original quoted-string is returned here, including
+ * escaping for any contained characters. In other words, if the
+ * header was:
+ * <pre>
+ * Warning: 110 fred "Response is stale"
+ * </pre>
+ * then this method will return <code>"\"Response is stale\""</code>
+ * (surrounding quotes included).
+ * @return {@link String}
+ */
+ public String getWarnText() { return warnText; }
+
+ /** Returns the date and time when this warning was added, or
+ * <code>null</code> if a warning date was not supplied in the
+ * header.
+ * @return {@link Date}
+ */
+ public Date getWarnDate() { return warnDate; }
+
+ /** Formats a <code>WarningValue</code> as a {@link String}
+ * suitable for including in a header. For example, you can:
+ * <pre>
+ * WarningValue wv = ...;
+ * HttpResponse resp = ...;
+ * resp.addHeader("Warning", wv.toString());
+ * </pre>
+ * @return {@link String}
+ */
+ @Override
+ public String toString() {
+ if (warnDate != null) {
+ return String.format("%d %s %s \"%s\"", warnCode,
+ warnAgent, warnText, DateUtils.formatDate(warnDate));
+ } else {
+ return String.format("%d %s %s", warnCode, warnAgent, warnText);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/package.html b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/package.html
new file mode 100644
index 000000000..4c208e7a9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/cache/package.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+====================================================================
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+====================================================================
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the Apache Software Foundation. For more
+information on the Apache Software Foundation, please see
+<http://www.apache.org/>.
+-->
+</head>
+<body bgcolor="white">
+
+<p>
+This package contains a cache module that can be used for HTTP/1.1
+client-side caching. The primary classes in this package are the
+{@link org.apache.http.impl.client.cache.CachingHttpClient},
+which is a drop-in replacement for
+a {@link org.apache.http.impl.client.DefaultHttpClient} that adds
+caching, and the {@link org.apache.http.impl.client.cache.CacheConfig}
+class that can be used for configuring it.
+</p>
+</body>
+</html>
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/package-info.java
new file mode 100644
index 000000000..1efbf4cec
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/client/package-info.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default HTTP client implementation.
+ * <p/>
+ * The usual execution flow can be demonstrated by the code snippet below:
+ * <pre>
+ * CloseableHttpClient httpclient = HttpClients.createDefault();
+ * try {
+ * HttpGet httpGet = new HttpGet("http://targethost/homepage");
+ * CloseableHttpResponse response = httpclient.execute(httpGet);
+ * try {
+ * System.out.println(response.getStatusLine());
+ * HttpEntity entity = response.getEntity();
+ * // do something useful with the response body
+ * // and ensure it is fully consumed
+ * EntityUtils.consume(entity);
+ * } finally {
+ * response.close();
+ * }
+ * } finally {
+ * httpclient.close();
+ * }
+ * </pre>
+ */
+package ch.boye.httpclientandroidlib.impl.client;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java
new file mode 100644
index 000000000..ea2524f6a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java
@@ -0,0 +1,369 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Abstract adapter from {@link OperatedClientConnection operated} to
+ * {@link ManagedClientConnection managed} client connections.
+ * Read and write methods are delegated to the wrapped connection.
+ * Operations affecting the connection state have to be implemented
+ * by derived classes. Operations for querying the connection state
+ * are delegated to the wrapped connection if there is one, or
+ * return a default value if there is none.
+ * <p>
+ * This adapter tracks the checkpoints for reusable communication states,
+ * as indicated by {@link #markReusable markReusable} and queried by
+ * {@link #isMarkedReusable isMarkedReusable}.
+ * All send and receive operations will automatically clear the mark.
+ * <p>
+ * Connection release calls are delegated to the connection manager,
+ * if there is one. {@link #abortConnection abortConnection} will
+ * clear the reusability mark first. The connection manager is
+ * expected to tolerate multiple calls to the release method.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+@NotThreadSafe
+public abstract class AbstractClientConnAdapter implements ManagedClientConnection, HttpContext {
+
+ /**
+ * The connection manager.
+ */
+ private final ClientConnectionManager connManager;
+
+ /** The wrapped connection. */
+ private volatile OperatedClientConnection wrappedConnection;
+
+ /** The reusability marker. */
+ private volatile boolean markedReusable;
+
+ /** True if the connection has been shut down or released. */
+ private volatile boolean released;
+
+ /** The duration this is valid for while idle (in ms). */
+ private volatile long duration;
+
+ /**
+ * Creates a new connection adapter.
+ * The adapter is initially <i>not</i>
+ * {@link #isMarkedReusable marked} as reusable.
+ *
+ * @param mgr the connection manager, or <code>null</code>
+ * @param conn the connection to wrap, or <code>null</code>
+ */
+ protected AbstractClientConnAdapter(final ClientConnectionManager mgr,
+ final OperatedClientConnection conn) {
+ super();
+ connManager = mgr;
+ wrappedConnection = conn;
+ markedReusable = false;
+ released = false;
+ duration = Long.MAX_VALUE;
+ }
+
+ /**
+ * Detaches this adapter from the wrapped connection.
+ * This adapter becomes useless.
+ */
+ protected synchronized void detach() {
+ wrappedConnection = null;
+ duration = Long.MAX_VALUE;
+ }
+
+ protected OperatedClientConnection getWrappedConnection() {
+ return wrappedConnection;
+ }
+
+ protected ClientConnectionManager getManager() {
+ return connManager;
+ }
+
+ /**
+ * @deprecated (4.1) use {@link #assertValid(OperatedClientConnection)}
+ */
+ @Deprecated
+ protected final void assertNotAborted() throws InterruptedIOException {
+ if (isReleased()) {
+ throw new InterruptedIOException("Connection has been shut down");
+ }
+ }
+
+ /**
+ * @since 4.1
+ * @return value of released flag
+ */
+ protected boolean isReleased() {
+ return released;
+ }
+
+ /**
+ * Asserts that there is a valid wrapped connection to delegate to.
+ *
+ * @throws ConnectionShutdownException if there is no wrapped connection
+ * or connection has been aborted
+ */
+ protected final void assertValid(
+ final OperatedClientConnection wrappedConn) throws ConnectionShutdownException {
+ if (isReleased() || wrappedConn == null) {
+ throw new ConnectionShutdownException();
+ }
+ }
+
+ public boolean isOpen() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ if (conn == null) {
+ return false;
+ }
+
+ return conn.isOpen();
+ }
+
+ public boolean isStale() {
+ if (isReleased()) {
+ return true;
+ }
+ final OperatedClientConnection conn = getWrappedConnection();
+ if (conn == null) {
+ return true;
+ }
+
+ return conn.isStale();
+ }
+
+ public void setSocketTimeout(final int timeout) {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ conn.setSocketTimeout(timeout);
+ }
+
+ public int getSocketTimeout() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.getSocketTimeout();
+ }
+
+ public HttpConnectionMetrics getMetrics() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.getMetrics();
+ }
+
+ public void flush() throws IOException {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ conn.flush();
+ }
+
+ public boolean isResponseAvailable(final int timeout) throws IOException {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.isResponseAvailable(timeout);
+ }
+
+ public void receiveResponseEntity(final HttpResponse response)
+ throws HttpException, IOException {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ unmarkReusable();
+ conn.receiveResponseEntity(response);
+ }
+
+ public HttpResponse receiveResponseHeader()
+ throws HttpException, IOException {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ unmarkReusable();
+ return conn.receiveResponseHeader();
+ }
+
+ public void sendRequestEntity(final HttpEntityEnclosingRequest request)
+ throws HttpException, IOException {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ unmarkReusable();
+ conn.sendRequestEntity(request);
+ }
+
+ public void sendRequestHeader(final HttpRequest request)
+ throws HttpException, IOException {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ unmarkReusable();
+ conn.sendRequestHeader(request);
+ }
+
+ public InetAddress getLocalAddress() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.getLocalAddress();
+ }
+
+ public int getLocalPort() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.getLocalPort();
+ }
+
+ public InetAddress getRemoteAddress() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.getRemoteAddress();
+ }
+
+ public int getRemotePort() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.getRemotePort();
+ }
+
+ public boolean isSecure() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ return conn.isSecure();
+ }
+
+ public void bind(final Socket socket) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Socket getSocket() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ if (!isOpen()) {
+ return null;
+ }
+ return conn.getSocket();
+ }
+
+ public SSLSession getSSLSession() {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ if (!isOpen()) {
+ return null;
+ }
+
+ SSLSession result = null;
+ final Socket sock = conn.getSocket();
+ if (sock instanceof SSLSocket) {
+ result = ((SSLSocket)sock).getSession();
+ }
+ return result;
+ }
+
+ public void markReusable() {
+ markedReusable = true;
+ }
+
+ public void unmarkReusable() {
+ markedReusable = false;
+ }
+
+ public boolean isMarkedReusable() {
+ return markedReusable;
+ }
+
+ public void setIdleDuration(final long duration, final TimeUnit unit) {
+ if(duration > 0) {
+ this.duration = unit.toMillis(duration);
+ } else {
+ this.duration = -1;
+ }
+ }
+
+ public synchronized void releaseConnection() {
+ if (released) {
+ return;
+ }
+ released = true;
+ connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
+ }
+
+ public synchronized void abortConnection() {
+ if (released) {
+ return;
+ }
+ released = true;
+ unmarkReusable();
+ try {
+ shutdown();
+ } catch (final IOException ignore) {
+ }
+ connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
+ }
+
+ public Object getAttribute(final String id) {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).getAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public Object removeAttribute(final String id) {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).removeAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ final OperatedClientConnection conn = getWrappedConnection();
+ assertValid(conn);
+ if (conn instanceof HttpContext) {
+ ((HttpContext) conn).setAttribute(id, obj);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPoolEntry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPoolEntry.java
new file mode 100644
index 000000000..cbbe727b5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPoolEntry.java
@@ -0,0 +1,262 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.RouteTracker;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * A pool entry for use by connection manager implementations.
+ * Pool entries work in conjunction with an
+ * {@link AbstractClientConnAdapter adapter}.
+ * The adapter is handed out to applications that obtain a connection.
+ * The pool entry stores the underlying connection and tracks the
+ * {@link HttpRoute route} established.
+ * The adapter delegates methods for establishing the route to
+ * its pool entry.
+ * <p>
+ * If the managed connections is released or revoked, the adapter
+ * gets disconnected, but the pool entry still contains the
+ * underlying connection and the established route.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+public abstract class AbstractPoolEntry {
+
+ /** The connection operator. */
+ protected final ClientConnectionOperator connOperator;
+
+ /** The underlying connection being pooled or used. */
+ protected final OperatedClientConnection connection;
+
+ /** The route for which this entry gets allocated. */
+ //@@@ currently accessed from connection manager(s) as attribute
+ //@@@ avoid that, derived classes should decide whether update is allowed
+ //@@@ SCCM: yes, TSCCM: no
+ protected volatile HttpRoute route;
+
+ /** Connection state object */
+ protected volatile Object state;
+
+ /** The tracked route, or <code>null</code> before tracking starts. */
+ protected volatile RouteTracker tracker;
+
+
+ /**
+ * Creates a new pool entry.
+ *
+ * @param connOperator the Connection Operator for this entry
+ * @param route the planned route for the connection,
+ * or <code>null</code>
+ */
+ protected AbstractPoolEntry(final ClientConnectionOperator connOperator,
+ final HttpRoute route) {
+ super();
+ Args.notNull(connOperator, "Connection operator");
+ this.connOperator = connOperator;
+ this.connection = connOperator.createConnection();
+ this.route = route;
+ this.tracker = null;
+ }
+
+ /**
+ * Returns the state object associated with this pool entry.
+ *
+ * @return The state object
+ */
+ public Object getState() {
+ return state;
+ }
+
+ /**
+ * Assigns a state object to this pool entry.
+ *
+ * @param state The state object
+ */
+ public void setState(final Object state) {
+ this.state = state;
+ }
+
+ /**
+ * Opens the underlying connection.
+ *
+ * @param route the route along which to open the connection
+ * @param context the context for opening the connection
+ * @param params the parameters for opening the connection
+ *
+ * @throws IOException in case of a problem
+ */
+ public void open(final HttpRoute route,
+ final HttpContext context, final HttpParams params)
+ throws IOException {
+
+ Args.notNull(route, "Route");
+ Args.notNull(params, "HTTP parameters");
+ if (this.tracker != null) {
+ Asserts.check(!this.tracker.isConnected(), "Connection already open");
+ }
+ // - collect the arguments
+ // - call the operator
+ // - update the tracking data
+ // In this order, we can be sure that only a successful
+ // opening of the connection will be tracked.
+
+ this.tracker = new RouteTracker(route);
+ final HttpHost proxy = route.getProxyHost();
+
+ connOperator.openConnection
+ (this.connection,
+ (proxy != null) ? proxy : route.getTargetHost(),
+ route.getLocalAddress(),
+ context, params);
+
+ final RouteTracker localTracker = tracker; // capture volatile
+
+ // If this tracker was reset while connecting,
+ // fail early.
+ if (localTracker == null) {
+ throw new InterruptedIOException("Request aborted");
+ }
+
+ if (proxy == null) {
+ localTracker.connectTarget(this.connection.isSecure());
+ } else {
+ localTracker.connectProxy(proxy, this.connection.isSecure());
+ }
+
+ }
+
+ /**
+ * Tracks tunnelling of the connection to the target.
+ * The tunnel has to be established outside by sending a CONNECT
+ * request to the (last) proxy.
+ *
+ * @param secure <code>true</code> if the tunnel should be
+ * considered secure, <code>false</code> otherwise
+ * @param params the parameters for tunnelling the connection
+ *
+ * @throws IOException in case of a problem
+ */
+ public void tunnelTarget(final boolean secure, final HttpParams params)
+ throws IOException {
+
+ Args.notNull(params, "HTTP parameters");
+ Asserts.notNull(this.tracker, "Route tracker");
+ Asserts.check(this.tracker.isConnected(), "Connection not open");
+ Asserts.check(!this.tracker.isTunnelled(), "Connection is already tunnelled");
+
+ this.connection.update(null, tracker.getTargetHost(),
+ secure, params);
+ this.tracker.tunnelTarget(secure);
+ }
+
+ /**
+ * Tracks tunnelling of the connection to a chained proxy.
+ * The tunnel has to be established outside by sending a CONNECT
+ * request to the previous proxy.
+ *
+ * @param next the proxy to which the tunnel was established.
+ * See {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection#tunnelProxy
+ * ManagedClientConnection.tunnelProxy}
+ * for details.
+ * @param secure <code>true</code> if the tunnel should be
+ * considered secure, <code>false</code> otherwise
+ * @param params the parameters for tunnelling the connection
+ *
+ * @throws IOException in case of a problem
+ */
+ public void tunnelProxy(final HttpHost next, final boolean secure, final HttpParams params)
+ throws IOException {
+
+ Args.notNull(next, "Next proxy");
+ Args.notNull(params, "Parameters");
+
+ Asserts.notNull(this.tracker, "Route tracker");
+ Asserts.check(this.tracker.isConnected(), "Connection not open");
+
+ this.connection.update(null, next, secure, params);
+ this.tracker.tunnelProxy(next, secure);
+ }
+
+ /**
+ * Layers a protocol on top of an established tunnel.
+ *
+ * @param context the context for layering
+ * @param params the parameters for layering
+ *
+ * @throws IOException in case of a problem
+ */
+ public void layerProtocol(final HttpContext context, final HttpParams params)
+ throws IOException {
+
+ //@@@ is context allowed to be null? depends on operator?
+ Args.notNull(params, "HTTP parameters");
+ Asserts.notNull(this.tracker, "Route tracker");
+ Asserts.check(this.tracker.isConnected(), "Connection not open");
+ Asserts.check(this.tracker.isTunnelled(), "Protocol layering without a tunnel not supported");
+ Asserts.check(!this.tracker.isLayered(), "Multiple protocol layering not supported");
+ // - collect the arguments
+ // - call the operator
+ // - update the tracking data
+ // In this order, we can be sure that only a successful
+ // layering on top of the connection will be tracked.
+
+ final HttpHost target = tracker.getTargetHost();
+
+ connOperator.updateSecureConnection(this.connection, target,
+ context, params);
+
+ this.tracker.layerProtocol(this.connection.isSecure());
+
+ }
+
+ /**
+ * Shuts down the entry.
+ *
+ * If {@link #open(HttpRoute, HttpContext, HttpParams)} is in progress,
+ * this will cause that open to possibly throw an {@link IOException}.
+ */
+ protected void shutdownEntry() {
+ tracker = null;
+ state = null;
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java
new file mode 100644
index 000000000..47f0feda5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java
@@ -0,0 +1,191 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Abstract adapter from pool {@link AbstractPoolEntry entries} to
+ * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection managed}
+ * client connections.
+ * The connection in the pool entry is used to initialize the base class.
+ * In addition, methods to establish a route are delegated to the
+ * pool entry. {@link #shutdown shutdown} and {@link #close close}
+ * will clear the tracked route in the pool entry and call the
+ * respective method of the wrapped connection.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+public abstract class AbstractPooledConnAdapter extends AbstractClientConnAdapter {
+
+ /** The wrapped pool entry. */
+ protected volatile AbstractPoolEntry poolEntry;
+
+ /**
+ * Creates a new connection adapter.
+ *
+ * @param manager the connection manager
+ * @param entry the pool entry for the connection being wrapped
+ */
+ protected AbstractPooledConnAdapter(final ClientConnectionManager manager,
+ final AbstractPoolEntry entry) {
+ super(manager, entry.connection);
+ this.poolEntry = entry;
+ }
+
+ public String getId() {
+ return null;
+ }
+
+ /**
+ * Obtains the pool entry.
+ *
+ * @return the pool entry, or <code>null</code> if detached
+ *
+ * @deprecated (4.0.1)
+ */
+ @Deprecated
+ protected AbstractPoolEntry getPoolEntry() {
+ return this.poolEntry;
+ }
+
+ /**
+ * Asserts that there is a valid pool entry.
+ *
+ * @throws ConnectionShutdownException if there is no pool entry
+ * or connection has been aborted
+ *
+ * @see #assertValid(OperatedClientConnection)
+ */
+ protected void assertValid(final AbstractPoolEntry entry) {
+ if (isReleased() || entry == null) {
+ throw new ConnectionShutdownException();
+ }
+ }
+
+ /**
+ * @deprecated (4.1) use {@link #assertValid(AbstractPoolEntry)}
+ */
+ @Deprecated
+ protected final void assertAttached() {
+ if (poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ }
+
+ /**
+ * Detaches this adapter from the wrapped connection.
+ * This adapter becomes useless.
+ */
+ @Override
+ protected synchronized void detach() {
+ poolEntry = null;
+ super.detach();
+ }
+
+ public HttpRoute getRoute() {
+ final AbstractPoolEntry entry = getPoolEntry();
+ assertValid(entry);
+ return (entry.tracker == null) ? null : entry.tracker.toRoute();
+ }
+
+ public void open(final HttpRoute route,
+ final HttpContext context, final HttpParams params)
+ throws IOException {
+ final AbstractPoolEntry entry = getPoolEntry();
+ assertValid(entry);
+ entry.open(route, context, params);
+ }
+
+ public void tunnelTarget(final boolean secure, final HttpParams params)
+ throws IOException {
+ final AbstractPoolEntry entry = getPoolEntry();
+ assertValid(entry);
+ entry.tunnelTarget(secure, params);
+ }
+
+ public void tunnelProxy(final HttpHost next, final boolean secure, final HttpParams params)
+ throws IOException {
+ final AbstractPoolEntry entry = getPoolEntry();
+ assertValid(entry);
+ entry.tunnelProxy(next, secure, params);
+ }
+
+ public void layerProtocol(final HttpContext context, final HttpParams params)
+ throws IOException {
+ final AbstractPoolEntry entry = getPoolEntry();
+ assertValid(entry);
+ entry.layerProtocol(context, params);
+ }
+
+ public void close() throws IOException {
+ final AbstractPoolEntry entry = getPoolEntry();
+ if (entry != null) {
+ entry.shutdownEntry();
+ }
+
+ final OperatedClientConnection conn = getWrappedConnection();
+ if (conn != null) {
+ conn.close();
+ }
+ }
+
+ public void shutdown() throws IOException {
+ final AbstractPoolEntry entry = getPoolEntry();
+ if (entry != null) {
+ entry.shutdownEntry();
+ }
+
+ final OperatedClientConnection conn = getWrappedConnection();
+ if (conn != null) {
+ conn.shutdown();
+ }
+ }
+
+ public Object getState() {
+ final AbstractPoolEntry entry = getPoolEntry();
+ assertValid(entry);
+ return entry.getState();
+ }
+
+ public void setState(final Object state) {
+ final AbstractPoolEntry entry = getPoolEntry();
+ assertValid(entry);
+ entry.setState(state);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicClientConnectionManager.java
new file mode 100644
index 000000000..176e28150
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicClientConnectionManager.java
@@ -0,0 +1,276 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * A connection manager for a single connection. This connection manager maintains only one active
+ * connection. Even though this class is fully thread-safe it ought to be used by one execution
+ * thread only, as only one thread a time can lease the connection at a time.
+ * <p/>
+ * This connection manager will make an effort to reuse the connection for subsequent requests
+ * with the same {@link HttpRoute route}. It will, however, close the existing connection and
+ * open it for the given route, if the route of the persistent connection does not match that
+ * of the connection request. If the connection has been already been allocated
+ * {@link IllegalStateException} is thrown.
+ * <p/>
+ * This connection manager implementation should be used inside an EJB container instead of
+ * {@link PoolingClientConnectionManager}.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link BasicHttpClientConnectionManager}.
+ */
+@ThreadSafe
+@Deprecated
+public class BasicClientConnectionManager implements ClientConnectionManager {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private static final AtomicLong COUNTER = new AtomicLong();
+
+ /** The message to be logged on multiple allocation. */
+ public final static String MISUSE_MESSAGE =
+ "Invalid use of BasicClientConnManager: connection still allocated.\n" +
+ "Make sure to release the connection before allocating another one.";
+
+ /** The schemes supported by this connection manager. */
+ private final SchemeRegistry schemeRegistry;
+
+ /** The operator for opening and updating connections. */
+ private final ClientConnectionOperator connOperator;
+
+ /** The one and only entry in this pool. */
+ @GuardedBy("this")
+ private HttpPoolEntry poolEntry;
+
+ /** The currently issued managed connection, if any. */
+ @GuardedBy("this")
+ private ManagedClientConnectionImpl conn;
+
+ /** Indicates whether this connection manager is shut down. */
+ @GuardedBy("this")
+ private volatile boolean shutdown;
+
+ /**
+ * Creates a new simple connection manager.
+ *
+ * @param schreg the scheme registry
+ */
+ public BasicClientConnectionManager(final SchemeRegistry schreg) {
+ Args.notNull(schreg, "Scheme registry");
+ this.schemeRegistry = schreg;
+ this.connOperator = createConnectionOperator(schreg);
+ }
+
+ public BasicClientConnectionManager() {
+ this(SchemeRegistryFactory.createDefault());
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally { // Make sure we call overridden method even if shutdown barfs
+ super.finalize();
+ }
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ return this.schemeRegistry;
+ }
+
+ protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry schreg) {
+ return new DefaultClientConnectionOperator(schreg);
+ }
+
+ public final ClientConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+
+ return new ClientConnectionRequest() {
+
+ public void abortRequest() {
+ // Nothing to abort, since requests are immediate.
+ }
+
+ public ManagedClientConnection getConnection(
+ final long timeout, final TimeUnit tunit) {
+ return BasicClientConnectionManager.this.getConnection(
+ route, state);
+ }
+
+ };
+ }
+
+ private void assertNotShutdown() {
+ Asserts.check(!this.shutdown, "Connection manager has been shut down");
+ }
+
+ ManagedClientConnection getConnection(final HttpRoute route, final Object state) {
+ Args.notNull(route, "Route");
+ synchronized (this) {
+ assertNotShutdown();
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Get connection for route " + route);
+ }
+ Asserts.check(this.conn == null, MISUSE_MESSAGE);
+ if (this.poolEntry != null && !this.poolEntry.getPlannedRoute().equals(route)) {
+ this.poolEntry.close();
+ this.poolEntry = null;
+ }
+ if (this.poolEntry == null) {
+ final String id = Long.toString(COUNTER.getAndIncrement());
+ final OperatedClientConnection conn = this.connOperator.createConnection();
+ this.poolEntry = new HttpPoolEntry(this.log, id, route, conn, 0, TimeUnit.MILLISECONDS);
+ }
+ final long now = System.currentTimeMillis();
+ if (this.poolEntry.isExpired(now)) {
+ this.poolEntry.close();
+ this.poolEntry.getTracker().reset();
+ }
+ this.conn = new ManagedClientConnectionImpl(this, this.connOperator, this.poolEntry);
+ return this.conn;
+ }
+ }
+
+ private void shutdownConnection(final HttpClientConnection conn) {
+ try {
+ conn.shutdown();
+ } catch (final IOException iox) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("I/O exception shutting down connection", iox);
+ }
+ }
+ }
+
+ public void releaseConnection(final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) {
+ Args.check(conn instanceof ManagedClientConnectionImpl, "Connection class mismatch, " +
+ "connection not obtained from this manager");
+ final ManagedClientConnectionImpl managedConn = (ManagedClientConnectionImpl) conn;
+ synchronized (managedConn) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Releasing connection " + conn);
+ }
+ if (managedConn.getPoolEntry() == null) {
+ return; // already released
+ }
+ final ClientConnectionManager manager = managedConn.getManager();
+ Asserts.check(manager == this, "Connection not obtained from this manager");
+ synchronized (this) {
+ if (this.shutdown) {
+ shutdownConnection(managedConn);
+ return;
+ }
+ try {
+ if (managedConn.isOpen() && !managedConn.isMarkedReusable()) {
+ shutdownConnection(managedConn);
+ }
+ if (managedConn.isMarkedReusable()) {
+ this.poolEntry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS);
+ if (this.log.isDebugEnabled()) {
+ final String s;
+ if (keepalive > 0) {
+ s = "for " + keepalive + " " + tunit;
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection can be kept alive " + s);
+ }
+ }
+ } finally {
+ managedConn.detach();
+ this.conn = null;
+ if (this.poolEntry.isClosed()) {
+ this.poolEntry = null;
+ }
+ }
+ }
+ }
+ }
+
+ public void closeExpiredConnections() {
+ synchronized (this) {
+ assertNotShutdown();
+ final long now = System.currentTimeMillis();
+ if (this.poolEntry != null && this.poolEntry.isExpired(now)) {
+ this.poolEntry.close();
+ this.poolEntry.getTracker().reset();
+ }
+ }
+ }
+
+ public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
+ Args.notNull(tunit, "Time unit");
+ synchronized (this) {
+ assertNotShutdown();
+ long time = tunit.toMillis(idletime);
+ if (time < 0) {
+ time = 0;
+ }
+ final long deadline = System.currentTimeMillis() - time;
+ if (this.poolEntry != null && this.poolEntry.getUpdated() <= deadline) {
+ this.poolEntry.close();
+ this.poolEntry.getTracker().reset();
+ }
+ }
+ }
+
+ public void shutdown() {
+ synchronized (this) {
+ this.shutdown = true;
+ try {
+ if (this.poolEntry != null) {
+ this.poolEntry.close();
+ }
+ } finally {
+ this.poolEntry = null;
+ this.conn = null;
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicHttpClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicHttpClientConnectionManager.java
new file mode 100644
index 000000000..1049a4151
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/BasicHttpClientConnectionManager.java
@@ -0,0 +1,370 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.config.Registry;
+import ch.boye.httpclientandroidlib.config.RegistryBuilder;
+import ch.boye.httpclientandroidlib.config.SocketConfig;
+import ch.boye.httpclientandroidlib.conn.ConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.DnsResolver;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.HttpConnectionFactory;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.socket.ConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.socket.PlainConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.ssl.SSLConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * A connection manager for a single connection. This connection manager maintains only one active
+ * connection. Even though this class is fully thread-safe it ought to be used by one execution
+ * thread only, as only one thread a time can lease the connection at a time.
+ * <p/>
+ * This connection manager will make an effort to reuse the connection for subsequent requests
+ * with the same {@link HttpRoute route}. It will, however, close the existing connection and
+ * open it for the given route, if the route of the persistent connection does not match that
+ * of the connection request. If the connection has been already been allocated
+ * {@link IllegalStateException} is thrown.
+ * <p/>
+ * This connection manager implementation should be used inside an EJB container instead of
+ * {@link PoolingHttpClientConnectionManager}.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public class BasicHttpClientConnectionManager implements HttpClientConnectionManager, Closeable {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final HttpClientConnectionOperator connectionOperator;
+ private final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory;
+
+ @GuardedBy("this")
+ private ManagedHttpClientConnection conn;
+
+ @GuardedBy("this")
+ private HttpRoute route;
+
+ @GuardedBy("this")
+ private Object state;
+
+ @GuardedBy("this")
+ private long updated;
+
+ @GuardedBy("this")
+ private long expiry;
+
+ @GuardedBy("this")
+ private boolean leased;
+
+ @GuardedBy("this")
+ private SocketConfig socketConfig;
+
+ @GuardedBy("this")
+ private ConnectionConfig connConfig;
+
+ private final AtomicBoolean isShutdown;
+
+ private static Registry<ConnectionSocketFactory> getDefaultRegistry() {
+ return RegistryBuilder.<ConnectionSocketFactory>create()
+ .register("http", PlainConnectionSocketFactory.getSocketFactory())
+ .register("https", SSLConnectionSocketFactory.getSocketFactory())
+ .build();
+ }
+
+ public BasicHttpClientConnectionManager(
+ final Lookup<ConnectionSocketFactory> socketFactoryRegistry,
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,
+ final SchemePortResolver schemePortResolver,
+ final DnsResolver dnsResolver) {
+ super();
+ this.connectionOperator = new HttpClientConnectionOperator(
+ socketFactoryRegistry, schemePortResolver, dnsResolver);
+ this.connFactory = connFactory != null ? connFactory : ManagedHttpClientConnectionFactory.INSTANCE;
+ this.expiry = Long.MAX_VALUE;
+ this.socketConfig = SocketConfig.DEFAULT;
+ this.connConfig = ConnectionConfig.DEFAULT;
+ this.isShutdown = new AtomicBoolean(false);
+ }
+
+ public BasicHttpClientConnectionManager(
+ final Lookup<ConnectionSocketFactory> socketFactoryRegistry,
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory) {
+ this(socketFactoryRegistry, connFactory, null, null);
+ }
+
+ public BasicHttpClientConnectionManager(
+ final Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
+ this(socketFactoryRegistry, null, null, null);
+ }
+
+ public BasicHttpClientConnectionManager() {
+ this(getDefaultRegistry(), null, null, null);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally { // Make sure we call overridden method even if shutdown barfs
+ super.finalize();
+ }
+ }
+
+ public void close() {
+ shutdown();
+ }
+
+ HttpRoute getRoute() {
+ return route;
+ }
+
+ Object getState() {
+ return state;
+ }
+
+ public synchronized SocketConfig getSocketConfig() {
+ return socketConfig;
+ }
+
+ public synchronized void setSocketConfig(final SocketConfig socketConfig) {
+ this.socketConfig = socketConfig != null ? socketConfig : SocketConfig.DEFAULT;
+ }
+
+ public synchronized ConnectionConfig getConnectionConfig() {
+ return connConfig;
+ }
+
+ public synchronized void setConnectionConfig(final ConnectionConfig connConfig) {
+ this.connConfig = connConfig != null ? connConfig : ConnectionConfig.DEFAULT;
+ }
+
+ public final ConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+ Args.notNull(route, "Route");
+ return new ConnectionRequest() {
+
+ public boolean cancel() {
+ // Nothing to abort, since requests are immediate.
+ return false;
+ }
+
+ public HttpClientConnection get(final long timeout, final TimeUnit tunit) {
+ return BasicHttpClientConnectionManager.this.getConnection(
+ route, state);
+ }
+
+ };
+ }
+
+ private void closeConnection() {
+ if (this.conn != null) {
+ this.log.debug("Closing connection");
+ try {
+ this.conn.close();
+ } catch (final IOException iox) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("I/O exception closing connection", iox);
+ }
+ }
+ this.conn = null;
+ }
+ }
+
+ private void shutdownConnection() {
+ if (this.conn != null) {
+ this.log.debug("Shutting down connection");
+ try {
+ this.conn.shutdown();
+ } catch (final IOException iox) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("I/O exception shutting down connection", iox);
+ }
+ }
+ this.conn = null;
+ }
+ }
+
+ private void checkExpiry() {
+ if (this.conn != null && System.currentTimeMillis() >= this.expiry) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection expired @ " + new Date(this.expiry));
+ }
+ closeConnection();
+ }
+ }
+
+ synchronized HttpClientConnection getConnection(final HttpRoute route, final Object state) {
+ Asserts.check(!this.isShutdown.get(), "Connection manager has been shut down");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Get connection for route " + route);
+ }
+ Asserts.check(!this.leased, "Connection is still allocated");
+ if (!LangUtils.equals(this.route, route) || !LangUtils.equals(this.state, state)) {
+ closeConnection();
+ }
+ this.route = route;
+ this.state = state;
+ checkExpiry();
+ if (this.conn == null) {
+ this.conn = this.connFactory.create(route, this.connConfig);
+ }
+ this.leased = true;
+ return this.conn;
+ }
+
+ public synchronized void releaseConnection(
+ final HttpClientConnection conn,
+ final Object state,
+ final long keepalive, final TimeUnit tunit) {
+ Args.notNull(conn, "Connection");
+ Asserts.check(conn == this.conn, "Connection not obtained from this manager");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Releasing connection " + conn);
+ }
+ if (this.isShutdown.get()) {
+ return;
+ }
+ try {
+ this.updated = System.currentTimeMillis();
+ if (!this.conn.isOpen()) {
+ this.conn = null;
+ this.route = null;
+ this.conn = null;
+ this.expiry = Long.MAX_VALUE;
+ } else {
+ this.state = state;
+ if (this.log.isDebugEnabled()) {
+ final String s;
+ if (keepalive > 0) {
+ s = "for " + keepalive + " " + tunit;
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection can be kept alive " + s);
+ }
+ if (keepalive > 0) {
+ this.expiry = this.updated + tunit.toMillis(keepalive);
+ } else {
+ this.expiry = Long.MAX_VALUE;
+ }
+ }
+ } finally {
+ this.leased = false;
+ }
+ }
+
+ public void connect(
+ final HttpClientConnection conn,
+ final HttpRoute route,
+ final int connectTimeout,
+ final HttpContext context) throws IOException {
+ Args.notNull(conn, "Connection");
+ Args.notNull(route, "HTTP route");
+ Asserts.check(conn == this.conn, "Connection not obtained from this manager");
+ final HttpHost host;
+ if (route.getProxyHost() != null) {
+ host = route.getProxyHost();
+ } else {
+ host = route.getTargetHost();
+ }
+ final InetSocketAddress localAddress = route.getLocalSocketAddress();
+ this.connectionOperator.connect(this.conn, host, localAddress,
+ connectTimeout, this.socketConfig, context);
+ }
+
+ public void upgrade(
+ final HttpClientConnection conn,
+ final HttpRoute route,
+ final HttpContext context) throws IOException {
+ Args.notNull(conn, "Connection");
+ Args.notNull(route, "HTTP route");
+ Asserts.check(conn == this.conn, "Connection not obtained from this manager");
+ this.connectionOperator.upgrade(this.conn, route.getTargetHost(), context);
+ }
+
+ public void routeComplete(
+ final HttpClientConnection conn,
+ final HttpRoute route,
+ final HttpContext context) throws IOException {
+ }
+
+ public synchronized void closeExpiredConnections() {
+ if (this.isShutdown.get()) {
+ return;
+ }
+ if (!this.leased) {
+ checkExpiry();
+ }
+ }
+
+ public synchronized void closeIdleConnections(final long idletime, final TimeUnit tunit) {
+ Args.notNull(tunit, "Time unit");
+ if (this.isShutdown.get()) {
+ return;
+ }
+ if (!this.leased) {
+ long time = tunit.toMillis(idletime);
+ if (time < 0) {
+ time = 0;
+ }
+ final long deadline = System.currentTimeMillis() - time;
+ if (this.updated <= deadline) {
+ closeConnection();
+ }
+ }
+ }
+
+ public synchronized void shutdown() {
+ if (this.isShutdown.compareAndSet(false, true)) {
+ shutdownConnection();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPool.java
new file mode 100644
index 000000000..040960c71
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPool.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.pool.AbstractConnPool;
+import ch.boye.httpclientandroidlib.pool.ConnFactory;
+
+/**
+ * @since 4.3
+ */
+@ThreadSafe
+class CPool extends AbstractConnPool<HttpRoute, ManagedHttpClientConnection, CPoolEntry> {
+
+ private static final AtomicLong COUNTER = new AtomicLong();
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(CPool.class);
+ private final long timeToLive;
+ private final TimeUnit tunit;
+
+ public CPool(
+ final ConnFactory<HttpRoute, ManagedHttpClientConnection> connFactory,
+ final int defaultMaxPerRoute, final int maxTotal,
+ final long timeToLive, final TimeUnit tunit) {
+ super(connFactory, defaultMaxPerRoute, maxTotal);
+ this.timeToLive = timeToLive;
+ this.tunit = tunit;
+ }
+
+ @Override
+ protected CPoolEntry createEntry(final HttpRoute route, final ManagedHttpClientConnection conn) {
+ final String id = Long.toString(COUNTER.getAndIncrement());
+ return new CPoolEntry(this.log, id, route, conn, this.timeToLive, this.tunit);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolEntry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolEntry.java
new file mode 100644
index 000000000..f5ecfdc5e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolEntry.java
@@ -0,0 +1,101 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.pool.PoolEntry;
+
+/**
+ * @since 4.3
+ */
+@ThreadSafe
+class CPoolEntry extends PoolEntry<HttpRoute, ManagedHttpClientConnection> {
+
+ public HttpClientAndroidLog log;
+ private volatile boolean routeComplete;
+
+ public CPoolEntry(
+ final HttpClientAndroidLog log,
+ final String id,
+ final HttpRoute route,
+ final ManagedHttpClientConnection conn,
+ final long timeToLive, final TimeUnit tunit) {
+ super(id, route, conn, timeToLive, tunit);
+ this.log = log;
+ }
+
+ public void markRouteComplete() {
+ this.routeComplete = true;
+ }
+
+ public boolean isRouteComplete() {
+ return this.routeComplete;
+ }
+
+ public void closeConnection() throws IOException {
+ final HttpClientConnection conn = getConnection();
+ conn.close();
+ }
+
+ public void shutdownConnection() throws IOException {
+ final HttpClientConnection conn = getConnection();
+ conn.shutdown();
+ }
+
+ @Override
+ public boolean isExpired(final long now) {
+ final boolean expired = super.isExpired(now);
+ if (expired && this.log.isDebugEnabled()) {
+ this.log.debug("Connection " + this + " expired @ " + new Date(getExpiry()));
+ }
+ return expired;
+ }
+
+ @Override
+ public boolean isClosed() {
+ final HttpClientConnection conn = getConnection();
+ return !conn.isOpen();
+ }
+
+ @Override
+ public void close() {
+ try {
+ closeConnection();
+ } catch (final IOException ex) {
+ this.log.debug("I/O error closing connection", ex);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolProxy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolProxy.java
new file mode 100644
index 000000000..9ac67a10d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/CPoolProxy.java
@@ -0,0 +1,245 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+
+import javax.net.ssl.SSLSession;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * @since 4.3
+ */
+@NotThreadSafe
+class CPoolProxy implements ManagedHttpClientConnection, HttpContext {
+
+ private volatile CPoolEntry poolEntry;
+
+ CPoolProxy(final CPoolEntry entry) {
+ super();
+ this.poolEntry = entry;
+ }
+
+ CPoolEntry getPoolEntry() {
+ return this.poolEntry;
+ }
+
+ CPoolEntry detach() {
+ final CPoolEntry local = this.poolEntry;
+ this.poolEntry = null;
+ return local;
+ }
+
+ ManagedHttpClientConnection getConnection() {
+ final CPoolEntry local = this.poolEntry;
+ if (local == null) {
+ return null;
+ }
+ return local.getConnection();
+ }
+
+ ManagedHttpClientConnection getValidConnection() {
+ final ManagedHttpClientConnection conn = getConnection();
+ if (conn == null) {
+ throw new ConnectionShutdownException();
+ }
+ return conn;
+ }
+
+ public void close() throws IOException {
+ final CPoolEntry local = this.poolEntry;
+ if (local != null) {
+ local.closeConnection();
+ }
+ }
+
+ public void shutdown() throws IOException {
+ final CPoolEntry local = this.poolEntry;
+ if (local != null) {
+ local.shutdownConnection();
+ }
+ }
+
+ public boolean isOpen() {
+ final CPoolEntry local = this.poolEntry;
+ if (local != null) {
+ return !local.isClosed();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isStale() {
+ final HttpClientConnection conn = getConnection();
+ if (conn != null) {
+ return conn.isStale();
+ } else {
+ return true;
+ }
+ }
+
+ public void setSocketTimeout(final int timeout) {
+ getValidConnection().setSocketTimeout(timeout);
+ }
+
+ public int getSocketTimeout() {
+ return getValidConnection().getSocketTimeout();
+ }
+
+ public String getId() {
+ return getValidConnection().getId();
+ }
+
+ public void bind(final Socket socket) throws IOException {
+ getValidConnection().bind(socket);
+ }
+
+ public Socket getSocket() {
+ return getValidConnection().getSocket();
+ }
+
+ public SSLSession getSSLSession() {
+ return getValidConnection().getSSLSession();
+ }
+
+ public boolean isResponseAvailable(final int timeout) throws IOException {
+ return getValidConnection().isResponseAvailable(timeout);
+ }
+
+ public void sendRequestHeader(final HttpRequest request) throws HttpException, IOException {
+ getValidConnection().sendRequestHeader(request);
+ }
+
+ public void sendRequestEntity(final HttpEntityEnclosingRequest request) throws HttpException, IOException {
+ getValidConnection().sendRequestEntity(request);
+ }
+
+ public HttpResponse receiveResponseHeader() throws HttpException, IOException {
+ return getValidConnection().receiveResponseHeader();
+ }
+
+ public void receiveResponseEntity(final HttpResponse response) throws HttpException, IOException {
+ getValidConnection().receiveResponseEntity(response);
+ }
+
+ public void flush() throws IOException {
+ getValidConnection().flush();
+ }
+
+ public HttpConnectionMetrics getMetrics() {
+ return getValidConnection().getMetrics();
+ }
+
+ public InetAddress getLocalAddress() {
+ return getValidConnection().getLocalAddress();
+ }
+
+ public int getLocalPort() {
+ return getValidConnection().getLocalPort();
+ }
+
+ public InetAddress getRemoteAddress() {
+ return getValidConnection().getRemoteAddress();
+ }
+
+ public int getRemotePort() {
+ return getValidConnection().getRemotePort();
+ }
+
+ public Object getAttribute(final String id) {
+ final ManagedHttpClientConnection conn = getValidConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).getAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ final ManagedHttpClientConnection conn = getValidConnection();
+ if (conn instanceof HttpContext) {
+ ((HttpContext) conn).setAttribute(id, obj);
+ }
+ }
+
+ public Object removeAttribute(final String id) {
+ final ManagedHttpClientConnection conn = getValidConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).removeAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("CPoolProxy{");
+ final ManagedHttpClientConnection conn = getConnection();
+ if (conn != null) {
+ sb.append(conn);
+ } else {
+ sb.append("detached");
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public static HttpClientConnection newProxy(final CPoolEntry poolEntry) {
+ return new CPoolProxy(poolEntry);
+ }
+
+ private static CPoolProxy getProxy(final HttpClientConnection conn) {
+ if (!CPoolProxy.class.isInstance(conn)) {
+ throw new IllegalStateException("Unexpected connection proxy class: " + conn.getClass());
+ }
+ return CPoolProxy.class.cast(conn);
+ }
+
+ public static CPoolEntry getPoolEntry(final HttpClientConnection proxy) {
+ final CPoolEntry entry = getProxy(proxy).getPoolEntry();
+ if (entry == null) {
+ throw new ConnectionShutdownException();
+ }
+ return entry;
+ }
+
+ public static CPoolEntry detach(final HttpClientConnection conn) {
+ return getProxy(conn).detach();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ConnectionShutdownException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ConnectionShutdownException.java
new file mode 100644
index 000000000..03820a38f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ConnectionShutdownException.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals that the connection has been shut down or released back to the
+ * the connection pool
+ *
+ * @since 4.1
+ */
+@Immutable
+public class ConnectionShutdownException extends IllegalStateException {
+
+ private static final long serialVersionUID = 5868657401162844497L;
+
+ /**
+ * Creates a new ConnectionShutdownException with a <tt>null</tt> detail message.
+ */
+ public ConnectionShutdownException() {
+ super();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnection.java
new file mode 100644
index 000000000..f9003b144
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnection.java
@@ -0,0 +1,292 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.impl.SocketHttpClientConnection;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.params.BasicHttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.params.HttpProtocolParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of an operated client connection.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ManagedHttpClientConnectionFactory}.
+ */
+@NotThreadSafe // connSecure, targetHost
+@Deprecated
+public class DefaultClientConnection extends SocketHttpClientConnection
+ implements OperatedClientConnection, ManagedHttpClientConnection, HttpContext {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+ public HttpClientAndroidLog headerLog = new HttpClientAndroidLog("ch.boye.httpclientandroidlib.headers");
+ public HttpClientAndroidLog wireLog = new HttpClientAndroidLog("ch.boye.httpclientandroidlib.wire");
+
+ /** The unconnected socket */
+ private volatile Socket socket;
+
+ /** The target host of this connection. */
+ private HttpHost targetHost;
+
+ /** Whether this connection is secure. */
+ private boolean connSecure;
+
+ /** True if this connection was shutdown. */
+ private volatile boolean shutdown;
+
+ /** connection specific attributes */
+ private final Map<String, Object> attributes;
+
+ public DefaultClientConnection() {
+ super();
+ this.attributes = new HashMap<String, Object>();
+ }
+
+ public String getId() {
+ return null;
+ }
+
+ public final HttpHost getTargetHost() {
+ return this.targetHost;
+ }
+
+ public final boolean isSecure() {
+ return this.connSecure;
+ }
+
+ @Override
+ public final Socket getSocket() {
+ return this.socket;
+ }
+
+ public SSLSession getSSLSession() {
+ if (this.socket instanceof SSLSocket) {
+ return ((SSLSocket) this.socket).getSession();
+ } else {
+ return null;
+ }
+ }
+
+ public void opening(final Socket sock, final HttpHost target) throws IOException {
+ assertNotOpen();
+ this.socket = sock;
+ this.targetHost = target;
+
+ // Check for shutdown after assigning socket, so that
+ if (this.shutdown) {
+ sock.close(); // allow this to throw...
+ // ...but if it doesn't, explicitly throw one ourselves.
+ throw new InterruptedIOException("Connection already shutdown");
+ }
+ }
+
+ public void openCompleted(final boolean secure, final HttpParams params) throws IOException {
+ Args.notNull(params, "Parameters");
+ assertNotOpen();
+ this.connSecure = secure;
+ bind(this.socket, params);
+ }
+
+ /**
+ * Force-closes this connection.
+ * If the connection is still in the process of being open (the method
+ * {@link #opening opening} was already called but
+ * {@link #openCompleted openCompleted} was not), the associated
+ * socket that is being connected to a remote address will be closed.
+ * That will interrupt a thread that is blocked on connecting
+ * the socket.
+ * If the connection is not yet open, this will prevent the connection
+ * from being opened.
+ *
+ * @throws IOException in case of a problem
+ */
+ @Override
+ public void shutdown() throws IOException {
+ shutdown = true;
+ try {
+ super.shutdown();
+ if (log.isDebugEnabled()) {
+ log.debug("Connection " + this + " shut down");
+ }
+ final Socket sock = this.socket; // copy volatile attribute
+ if (sock != null) {
+ sock.close();
+ }
+ } catch (final IOException ex) {
+ log.debug("I/O error shutting down connection", ex);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ super.close();
+ if (log.isDebugEnabled()) {
+ log.debug("Connection " + this + " closed");
+ }
+ } catch (final IOException ex) {
+ log.debug("I/O error closing connection", ex);
+ }
+ }
+
+ @Override
+ protected SessionInputBuffer createSessionInputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ SessionInputBuffer inbuffer = super.createSessionInputBuffer(
+ socket,
+ buffersize > 0 ? buffersize : 8192,
+ params);
+ if (wireLog.isDebugEnabled()) {
+ inbuffer = new LoggingSessionInputBuffer(
+ inbuffer,
+ new Wire(wireLog),
+ HttpProtocolParams.getHttpElementCharset(params));
+ }
+ return inbuffer;
+ }
+
+ @Override
+ protected SessionOutputBuffer createSessionOutputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ SessionOutputBuffer outbuffer = super.createSessionOutputBuffer(
+ socket,
+ buffersize > 0 ? buffersize : 8192,
+ params);
+ if (wireLog.isDebugEnabled()) {
+ outbuffer = new LoggingSessionOutputBuffer(
+ outbuffer,
+ new Wire(wireLog),
+ HttpProtocolParams.getHttpElementCharset(params));
+ }
+ return outbuffer;
+ }
+
+ @Override
+ protected HttpMessageParser<HttpResponse> createResponseParser(
+ final SessionInputBuffer buffer,
+ final HttpResponseFactory responseFactory,
+ final HttpParams params) {
+ // override in derived class to specify a line parser
+ return new DefaultHttpResponseParser
+ (buffer, null, responseFactory, params);
+ }
+
+ public void bind(final Socket socket) throws IOException {
+ bind(socket, new BasicHttpParams());
+ }
+
+ public void update(final Socket sock, final HttpHost target,
+ final boolean secure, final HttpParams params)
+ throws IOException {
+
+ assertOpen();
+ Args.notNull(target, "Target host");
+ Args.notNull(params, "Parameters");
+
+ if (sock != null) {
+ this.socket = sock;
+ bind(sock, params);
+ }
+ targetHost = target;
+ connSecure = secure;
+ }
+
+ @Override
+ public HttpResponse receiveResponseHeader() throws HttpException, IOException {
+ final HttpResponse response = super.receiveResponseHeader();
+ if (log.isDebugEnabled()) {
+ log.debug("Receiving response: " + response.getStatusLine());
+ }
+ if (headerLog.isDebugEnabled()) {
+ headerLog.debug("<< " + response.getStatusLine().toString());
+ final Header[] headers = response.getAllHeaders();
+ for (final Header header : headers) {
+ headerLog.debug("<< " + header.toString());
+ }
+ }
+ return response;
+ }
+
+ @Override
+ public void sendRequestHeader(final HttpRequest request) throws HttpException, IOException {
+ if (log.isDebugEnabled()) {
+ log.debug("Sending request: " + request.getRequestLine());
+ }
+ super.sendRequestHeader(request);
+ if (headerLog.isDebugEnabled()) {
+ headerLog.debug(">> " + request.getRequestLine().toString());
+ final Header[] headers = request.getAllHeaders();
+ for (final Header header : headers) {
+ headerLog.debug(">> " + header.toString());
+ }
+ }
+ }
+
+ public Object getAttribute(final String id) {
+ return this.attributes.get(id);
+ }
+
+ public Object removeAttribute(final String id) {
+ return this.attributes.remove(id);
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ this.attributes.put(id, obj);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java
new file mode 100644
index 000000000..3cdf706ec
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java
@@ -0,0 +1,263 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.client.protocol.ClientContext;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.conn.DnsResolver;
+import ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeLayeredSocketFactory;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeSocketFactory;
+import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Default implementation of a {@link ClientConnectionOperator}. It uses a {@link SchemeRegistry}
+ * to look up {@link SchemeSocketFactory} objects.
+ * <p>
+ * This connection operator is multihome network aware and will attempt to retry failed connects
+ * against all known IP addresses sequentially until the connect is successful or all known
+ * addresses fail to respond. Please note the same
+ * {@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#CONNECTION_TIMEOUT} value will be used
+ * for each connection attempt, so in the worst case the total elapsed time before timeout
+ * can be <code>CONNECTION_TIMEOUT * n</code> where <code>n</code> is the number of IP addresses
+ * of the given host. One can disable multihome support by overriding
+ * the {@link #resolveHostname(String)} method and returning only one IP address for the given
+ * host name.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_LINGER}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SO_REUSEADDR}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#TCP_NODELAY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link PoolingHttpClientConnectionManager}.
+ */
+@Deprecated
+@ThreadSafe
+public class DefaultClientConnectionOperator implements ClientConnectionOperator {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /** The scheme registry for looking up socket factories. */
+ protected final SchemeRegistry schemeRegistry; // @ThreadSafe
+
+ /** the custom-configured DNS lookup mechanism. */
+ protected final DnsResolver dnsResolver;
+
+ /**
+ * Creates a new client connection operator for the given scheme registry.
+ *
+ * @param schemes the scheme registry
+ *
+ * @since 4.2
+ */
+ public DefaultClientConnectionOperator(final SchemeRegistry schemes) {
+ Args.notNull(schemes, "Scheme registry");
+ this.schemeRegistry = schemes;
+ this.dnsResolver = new SystemDefaultDnsResolver();
+ }
+
+ /**
+ * Creates a new client connection operator for the given scheme registry
+ * and the given custom DNS lookup mechanism.
+ *
+ * @param schemes
+ * the scheme registry
+ * @param dnsResolver
+ * the custom DNS lookup mechanism
+ */
+ public DefaultClientConnectionOperator(final SchemeRegistry schemes,final DnsResolver dnsResolver) {
+ Args.notNull(schemes, "Scheme registry");
+
+ Args.notNull(dnsResolver, "DNS resolver");
+
+ this.schemeRegistry = schemes;
+ this.dnsResolver = dnsResolver;
+ }
+
+ public OperatedClientConnection createConnection() {
+ return new DefaultClientConnection();
+ }
+
+ private SchemeRegistry getSchemeRegistry(final HttpContext context) {
+ SchemeRegistry reg = (SchemeRegistry) context.getAttribute(
+ ClientContext.SCHEME_REGISTRY);
+ if (reg == null) {
+ reg = this.schemeRegistry;
+ }
+ return reg;
+ }
+
+ public void openConnection(
+ final OperatedClientConnection conn,
+ final HttpHost target,
+ final InetAddress local,
+ final HttpContext context,
+ final HttpParams params) throws IOException {
+ Args.notNull(conn, "Connection");
+ Args.notNull(target, "Target host");
+ Args.notNull(params, "HTTP parameters");
+ Asserts.check(!conn.isOpen(), "Connection must not be open");
+
+ final SchemeRegistry registry = getSchemeRegistry(context);
+ final Scheme schm = registry.getScheme(target.getSchemeName());
+ final SchemeSocketFactory sf = schm.getSchemeSocketFactory();
+
+ final InetAddress[] addresses = resolveHostname(target.getHostName());
+ final int port = schm.resolvePort(target.getPort());
+ for (int i = 0; i < addresses.length; i++) {
+ final InetAddress address = addresses[i];
+ final boolean last = i == addresses.length - 1;
+
+ Socket sock = sf.createSocket(params);
+ conn.opening(sock, target);
+
+ final InetSocketAddress remoteAddress = new HttpInetSocketAddress(target, address, port);
+ InetSocketAddress localAddress = null;
+ if (local != null) {
+ localAddress = new InetSocketAddress(local, 0);
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connecting to " + remoteAddress);
+ }
+ try {
+ final Socket connsock = sf.connectSocket(sock, remoteAddress, localAddress, params);
+ if (sock != connsock) {
+ sock = connsock;
+ conn.opening(sock, target);
+ }
+ prepareSocket(sock, context, params);
+ conn.openCompleted(sf.isSecure(sock), params);
+ return;
+ } catch (final ConnectException ex) {
+ if (last) {
+ throw ex;
+ }
+ } catch (final ConnectTimeoutException ex) {
+ if (last) {
+ throw ex;
+ }
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connect to " + remoteAddress + " timed out. " +
+ "Connection will be retried using another IP address");
+ }
+ }
+ }
+
+ public void updateSecureConnection(
+ final OperatedClientConnection conn,
+ final HttpHost target,
+ final HttpContext context,
+ final HttpParams params) throws IOException {
+ Args.notNull(conn, "Connection");
+ Args.notNull(target, "Target host");
+ Args.notNull(params, "Parameters");
+ Asserts.check(conn.isOpen(), "Connection must be open");
+
+ final SchemeRegistry registry = getSchemeRegistry(context);
+ final Scheme schm = registry.getScheme(target.getSchemeName());
+ Asserts.check(schm.getSchemeSocketFactory() instanceof SchemeLayeredSocketFactory,
+ "Socket factory must implement SchemeLayeredSocketFactory");
+ final SchemeLayeredSocketFactory lsf = (SchemeLayeredSocketFactory) schm.getSchemeSocketFactory();
+ final Socket sock = lsf.createLayeredSocket(
+ conn.getSocket(), target.getHostName(), schm.resolvePort(target.getPort()), params);
+ prepareSocket(sock, context, params);
+ conn.update(sock, target, lsf.isSecure(sock), params);
+ }
+
+ /**
+ * Performs standard initializations on a newly created socket.
+ *
+ * @param sock the socket to prepare
+ * @param context the context for the connection
+ * @param params the parameters from which to prepare the socket
+ *
+ * @throws IOException in case of an IO problem
+ */
+ protected void prepareSocket(
+ final Socket sock,
+ final HttpContext context,
+ final HttpParams params) throws IOException {
+ sock.setTcpNoDelay(HttpConnectionParams.getTcpNoDelay(params));
+ sock.setSoTimeout(HttpConnectionParams.getSoTimeout(params));
+
+ final int linger = HttpConnectionParams.getLinger(params);
+ if (linger >= 0) {
+ sock.setSoLinger(linger > 0, linger);
+ }
+ }
+
+ /**
+ * Resolves the given host name to an array of corresponding IP addresses, based on the
+ * configured name service on the provided DNS resolver. If one wasn't provided, the system
+ * configuration is used.
+ *
+ * @param host host name to resolve
+ * @return array of IP addresses
+ * @exception UnknownHostException if no IP address for the host could be determined.
+ *
+ * @see DnsResolver
+ * @see SystemDefaultDnsResolver
+ *
+ * @since 4.1
+ */
+ protected InetAddress[] resolveHostname(final String host) throws UnknownHostException {
+ return dnsResolver.resolve(host);
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParser.java
new file mode 100644
index 000000000..9f249e5f7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParser.java
@@ -0,0 +1,168 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.NoHttpResponseException;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.impl.DefaultHttpResponseFactory;
+import ch.boye.httpclientandroidlib.impl.io.AbstractMessageParser;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.LineParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Lenient HTTP response parser implementation that can skip malformed data until
+ * a valid HTTP response message head is encountered.
+ *
+ * @since 4.2
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public class DefaultHttpResponseParser extends AbstractMessageParser<HttpResponse> {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final HttpResponseFactory responseFactory;
+ private final CharArrayBuffer lineBuf;
+
+ /**
+ * @deprecated (4.3) use {@link DefaultHttpResponseParser#DefaultHttpResponseParser(
+ * SessionInputBuffer, LineParser, HttpResponseFactory, MessageConstraints)}
+ */
+ @Deprecated
+ public DefaultHttpResponseParser(
+ final SessionInputBuffer buffer,
+ final LineParser parser,
+ final HttpResponseFactory responseFactory,
+ final HttpParams params) {
+ super(buffer, parser, params);
+ Args.notNull(responseFactory, "Response factory");
+ this.responseFactory = responseFactory;
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ /**
+ * Creates new instance of DefaultHttpResponseParser.
+ *
+ * @param buffer the session input buffer.
+ * @param lineParser the line parser. If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.message.BasicLineParser#INSTANCE} will be used.
+ * @param responseFactory HTTP response factory. If <code>null</code>
+ * {@link DefaultHttpResponseFactory#INSTANCE} will be used.
+ * @param constraints the message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ *
+ * @since 4.3
+ */
+ public DefaultHttpResponseParser(
+ final SessionInputBuffer buffer,
+ final LineParser lineParser,
+ final HttpResponseFactory responseFactory,
+ final MessageConstraints constraints) {
+ super(buffer, lineParser, constraints);
+ this.responseFactory = responseFactory != null ? responseFactory :
+ DefaultHttpResponseFactory.INSTANCE;
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ /**
+ * Creates new instance of DefaultHttpResponseParser.
+ *
+ * @param buffer the session input buffer.
+ * @param constraints the message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ *
+ * @since 4.3
+ */
+ public DefaultHttpResponseParser(
+ final SessionInputBuffer buffer, final MessageConstraints constraints) {
+ this(buffer, null, null, constraints);
+ }
+
+ /**
+ * Creates new instance of DefaultHttpResponseParser.
+ *
+ * @param buffer the session input buffer.
+ *
+ * @since 4.3
+ */
+ public DefaultHttpResponseParser(final SessionInputBuffer buffer) {
+ this(buffer, null, null, MessageConstraints.DEFAULT);
+ }
+
+ @Override
+ protected HttpResponse parseHead(
+ final SessionInputBuffer sessionBuffer) throws IOException, HttpException {
+ //read out the HTTP status string
+ int count = 0;
+ ParserCursor cursor = null;
+ do {
+ // clear the buffer
+ this.lineBuf.clear();
+ final int i = sessionBuffer.readLine(this.lineBuf);
+ if (i == -1 && count == 0) {
+ // The server just dropped connection on us
+ throw new NoHttpResponseException("The target server failed to respond");
+ }
+ cursor = new ParserCursor(0, this.lineBuf.length());
+ if (lineParser.hasProtocolVersion(this.lineBuf, cursor)) {
+ // Got one
+ break;
+ } else if (i == -1 || reject(this.lineBuf, count)) {
+ // Giving up
+ throw new ProtocolException("The server failed to respond with a " +
+ "valid HTTP response");
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Garbage in response: " + this.lineBuf.toString());
+ }
+ count++;
+ } while(true);
+ //create the status line from the status string
+ final StatusLine statusline = lineParser.parseStatusLine(this.lineBuf, cursor);
+ return this.responseFactory.newHttpResponse(statusline, null);
+ }
+
+ protected boolean reject(final CharArrayBuffer line, final int count) {
+ return false;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParserFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParserFactory.java
new file mode 100644
index 000000000..a229b2ca6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpResponseParserFactory.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.impl.DefaultHttpResponseFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.BasicLineParser;
+import ch.boye.httpclientandroidlib.message.LineParser;
+
+/**
+ * Default factory for response message parsers.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultHttpResponseParserFactory implements HttpMessageParserFactory<HttpResponse> {
+
+ public static final DefaultHttpResponseParserFactory INSTANCE = new DefaultHttpResponseParserFactory();
+
+ private final LineParser lineParser;
+ private final HttpResponseFactory responseFactory;
+
+ public DefaultHttpResponseParserFactory(
+ final LineParser lineParser,
+ final HttpResponseFactory responseFactory) {
+ super();
+ this.lineParser = lineParser != null ? lineParser : BasicLineParser.INSTANCE;
+ this.responseFactory = responseFactory != null ? responseFactory
+ : DefaultHttpResponseFactory.INSTANCE;
+ }
+
+ public DefaultHttpResponseParserFactory(
+ final HttpResponseFactory responseFactory) {
+ this(null, responseFactory);
+ }
+
+ public DefaultHttpResponseParserFactory() {
+ this(null, null);
+ }
+
+ public HttpMessageParser<HttpResponse> create(final SessionInputBuffer buffer,
+ final MessageConstraints constraints) {
+ return new DefaultHttpResponseParser(buffer, lineParser, responseFactory, constraints);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java
new file mode 100644
index 000000000..4b3525329
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java
@@ -0,0 +1,123 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.params.ConnRouteParams;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Default implementation of an {@link HttpRoutePlanner}. This implementation
+ * is based on {@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames parameters}.
+ * It will not make use of any Java system properties, nor of system or
+ * browser proxy settings.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#DEFAULT_PROXY}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#LOCAL_ADDRESS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#FORCED_ROUTE}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultRoutePlanner}
+ */
+@ThreadSafe
+@Deprecated
+public class DefaultHttpRoutePlanner implements HttpRoutePlanner {
+
+ /** The scheme registry. */
+ protected final SchemeRegistry schemeRegistry; // class is @ThreadSafe
+
+ /**
+ * Creates a new default route planner.
+ *
+ * @param schreg the scheme registry
+ */
+ public DefaultHttpRoutePlanner(final SchemeRegistry schreg) {
+ Args.notNull(schreg, "Scheme registry");
+ schemeRegistry = schreg;
+ }
+
+ public HttpRoute determineRoute(final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context)
+ throws HttpException {
+
+ Args.notNull(request, "HTTP request");
+
+ // If we have a forced route, we can do without a target.
+ HttpRoute route =
+ ConnRouteParams.getForcedRoute(request.getParams());
+ if (route != null) {
+ return route;
+ }
+
+ // If we get here, there is no forced route.
+ // So we need a target to compute a route.
+
+ Asserts.notNull(target, "Target host");
+
+ final InetAddress local =
+ ConnRouteParams.getLocalAddress(request.getParams());
+ final HttpHost proxy =
+ ConnRouteParams.getDefaultProxy(request.getParams());
+
+ final Scheme schm;
+ try {
+ schm = this.schemeRegistry.getScheme(target.getSchemeName());
+ } catch (final IllegalStateException ex) {
+ throw new HttpException(ex.getMessage());
+ }
+ // as it is typically used for TLS/SSL, we assume that
+ // a layered scheme implies a secure connection
+ final boolean secure = schm.isLayered();
+
+ if (proxy == null) {
+ route = new HttpRoute(target, local, secure);
+ } else {
+ route = new HttpRoute(target, local, proxy, secure);
+ }
+ return route;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultManagedHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultManagedHttpClientConnection.java
new file mode 100644
index 000000000..c46b93405
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultManagedHttpClientConnection.java
@@ -0,0 +1,135 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.Socket;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.DefaultBHttpClientConnection;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * Default {@link ManagedHttpClientConnection} implementation.
+ * @since 4.3
+ */
+@NotThreadSafe
+public class DefaultManagedHttpClientConnection extends DefaultBHttpClientConnection
+ implements ManagedHttpClientConnection, HttpContext {
+
+ private final String id;
+ private final Map<String, Object> attributes;
+
+ private volatile boolean shutdown;
+
+ public DefaultManagedHttpClientConnection(
+ final String id,
+ final int buffersize,
+ final int fragmentSizeHint,
+ final CharsetDecoder chardecoder,
+ final CharsetEncoder charencoder,
+ final MessageConstraints constraints,
+ final ContentLengthStrategy incomingContentStrategy,
+ final ContentLengthStrategy outgoingContentStrategy,
+ final HttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+ final HttpMessageParserFactory<HttpResponse> responseParserFactory) {
+ super(buffersize, fragmentSizeHint, chardecoder, charencoder,
+ constraints, incomingContentStrategy, outgoingContentStrategy,
+ requestWriterFactory, responseParserFactory);
+ this.id = id;
+ this.attributes = new ConcurrentHashMap<String, Object>();
+ }
+
+ public DefaultManagedHttpClientConnection(
+ final String id,
+ final int buffersize) {
+ this(id, buffersize, buffersize, null, null, null, null, null, null, null);
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ @Override
+ public void shutdown() throws IOException {
+ this.shutdown = true;
+ super.shutdown();
+ }
+
+ public Object getAttribute(final String id) {
+ return this.attributes.get(id);
+ }
+
+ public Object removeAttribute(final String id) {
+ return this.attributes.remove(id);
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ this.attributes.put(id, obj);
+ }
+
+ @Override
+ public void bind(final Socket socket) throws IOException {
+ if (this.shutdown) {
+ socket.close(); // allow this to throw...
+ // ...but if it doesn't, explicitly throw one ourselves.
+ throw new InterruptedIOException("Connection already shutdown");
+ }
+ super.bind(socket);
+ }
+
+ @Override
+ public Socket getSocket() {
+ return super.getSocket();
+ }
+
+ public SSLSession getSSLSession() {
+ final Socket socket = super.getSocket();
+ if (socket instanceof SSLSocket) {
+ return ((SSLSocket) socket).getSession();
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultProxyRoutePlanner.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultProxyRoutePlanner.java
new file mode 100644
index 000000000..fd569556c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultProxyRoutePlanner.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Implementation of an {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner}
+ * that routes requests through a default proxy.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultProxyRoutePlanner extends DefaultRoutePlanner {
+
+ private final HttpHost proxy;
+
+ public DefaultProxyRoutePlanner(final HttpHost proxy, final SchemePortResolver schemePortResolver) {
+ super(schemePortResolver);
+ this.proxy = Args.notNull(proxy, "Proxy host");
+ }
+
+ public DefaultProxyRoutePlanner(final HttpHost proxy) {
+ this(proxy, null);
+ }
+
+ @Override
+ protected HttpHost determineProxy(
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) throws HttpException {
+ return proxy;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultResponseParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultResponseParser.java
new file mode 100644
index 000000000..e82452ff5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultResponseParser.java
@@ -0,0 +1,125 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.NoHttpResponseException;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.impl.io.AbstractMessageParser;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.LineParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Default HTTP response parser implementation.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnConnectionPNames#MAX_STATUS_LINE_GARBAGE}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link DefaultHttpResponseParser}
+ */
+@Deprecated
+@ThreadSafe // no public methods
+public class DefaultResponseParser extends AbstractMessageParser<HttpMessage> {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final HttpResponseFactory responseFactory;
+ private final CharArrayBuffer lineBuf;
+ private final int maxGarbageLines;
+
+ public DefaultResponseParser(
+ final SessionInputBuffer buffer,
+ final LineParser parser,
+ final HttpResponseFactory responseFactory,
+ final HttpParams params) {
+ super(buffer, parser, params);
+ Args.notNull(responseFactory, "Response factory");
+ this.responseFactory = responseFactory;
+ this.lineBuf = new CharArrayBuffer(128);
+ this.maxGarbageLines = getMaxGarbageLines(params);
+ }
+
+ protected int getMaxGarbageLines(final HttpParams params) {
+ return params.getIntParameter(
+ ch.boye.httpclientandroidlib.conn.params.ConnConnectionPNames.MAX_STATUS_LINE_GARBAGE,
+ Integer.MAX_VALUE);
+ }
+
+ @Override
+ protected HttpMessage parseHead(
+ final SessionInputBuffer sessionBuffer) throws IOException, HttpException {
+ //read out the HTTP status string
+ int count = 0;
+ ParserCursor cursor = null;
+ do {
+ // clear the buffer
+ this.lineBuf.clear();
+ final int i = sessionBuffer.readLine(this.lineBuf);
+ if (i == -1 && count == 0) {
+ // The server just dropped connection on us
+ throw new NoHttpResponseException("The target server failed to respond");
+ }
+ cursor = new ParserCursor(0, this.lineBuf.length());
+ if (lineParser.hasProtocolVersion(this.lineBuf, cursor)) {
+ // Got one
+ break;
+ } else if (i == -1 || count >= this.maxGarbageLines) {
+ // Giving up
+ throw new ProtocolException("The server failed to respond with a " +
+ "valid HTTP response");
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Garbage in response: " + this.lineBuf.toString());
+ }
+ count++;
+ } while(true);
+ //create the status line from the status string
+ final StatusLine statusline = lineParser.parseStatusLine(this.lineBuf, cursor);
+ return this.responseFactory.newHttpResponse(statusline, null);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultRoutePlanner.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultRoutePlanner.java
new file mode 100644
index 000000000..2c08a7118
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultRoutePlanner.java
@@ -0,0 +1,107 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.conn.UnsupportedSchemeException;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of an {@link HttpRoutePlanner}. It will not make use of
+ * any Java system properties, nor of system or browser proxy settings.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultRoutePlanner implements HttpRoutePlanner {
+
+ private final SchemePortResolver schemePortResolver;
+
+ public DefaultRoutePlanner(final SchemePortResolver schemePortResolver) {
+ super();
+ this.schemePortResolver = schemePortResolver != null ? schemePortResolver :
+ DefaultSchemePortResolver.INSTANCE;
+ }
+
+ public HttpRoute determineRoute(
+ final HttpHost host,
+ final HttpRequest request,
+ final HttpContext context) throws HttpException {
+ Args.notNull(request, "Request");
+ if (host == null) {
+ throw new ProtocolException("Target host is not specified");
+ }
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+ final RequestConfig config = clientContext.getRequestConfig();
+ final InetAddress local = config.getLocalAddress();
+ HttpHost proxy = config.getProxy();
+ if (proxy == null) {
+ proxy = determineProxy(host, request, context);
+ }
+
+ final HttpHost target;
+ if (host.getPort() <= 0) {
+ try {
+ target = new HttpHost(
+ host.getHostName(),
+ this.schemePortResolver.resolve(host),
+ host.getSchemeName());
+ } catch (final UnsupportedSchemeException ex) {
+ throw new HttpException(ex.getMessage());
+ }
+ } else {
+ target = host;
+ }
+ final boolean secure = target.getSchemeName().equalsIgnoreCase("https");
+ if (proxy == null) {
+ return new HttpRoute(target, local, secure);
+ } else {
+ return new HttpRoute(target, local, proxy, secure);
+ }
+ }
+
+ protected HttpHost determineProxy(
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) throws HttpException {
+ return null;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultSchemePortResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultSchemePortResolver.java
new file mode 100644
index 000000000..4b384f681
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/DefaultSchemePortResolver.java
@@ -0,0 +1,61 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.conn.UnsupportedSchemeException;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default {@link SchemePortResolver}.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultSchemePortResolver implements SchemePortResolver {
+
+ public static final DefaultSchemePortResolver INSTANCE = new DefaultSchemePortResolver();
+
+ public int resolve(final HttpHost host) throws UnsupportedSchemeException {
+ Args.notNull(host, "HTTP host");
+ final int port = host.getPort();
+ if (port > 0) {
+ return port;
+ }
+ final String name = host.getSchemeName();
+ if (name.equalsIgnoreCase("http")) {
+ return 80;
+ } else if (name.equalsIgnoreCase("https")) {
+ return 443;
+ } else {
+ throw new UnsupportedSchemeException(name + " protocol is not supported");
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpClientConnectionOperator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpClientConnectionOperator.java
new file mode 100644
index 000000000..a13368237
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpClientConnectionOperator.java
@@ -0,0 +1,173 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.config.SocketConfig;
+import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException;
+import ch.boye.httpclientandroidlib.conn.DnsResolver;
+import ch.boye.httpclientandroidlib.conn.HttpHostConnectException;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.conn.UnsupportedSchemeException;
+import ch.boye.httpclientandroidlib.conn.socket.ConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+
+@Immutable
+class HttpClientConnectionOperator {
+
+ static final String SOCKET_FACTORY_REGISTRY = "http.socket-factory-registry";
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final Lookup<ConnectionSocketFactory> socketFactoryRegistry;
+ private final SchemePortResolver schemePortResolver;
+ private final DnsResolver dnsResolver;
+
+ HttpClientConnectionOperator(
+ final Lookup<ConnectionSocketFactory> socketFactoryRegistry,
+ final SchemePortResolver schemePortResolver,
+ final DnsResolver dnsResolver) {
+ super();
+ Args.notNull(socketFactoryRegistry, "Socket factory registry");
+ this.socketFactoryRegistry = socketFactoryRegistry;
+ this.schemePortResolver = schemePortResolver != null ? schemePortResolver :
+ DefaultSchemePortResolver.INSTANCE;
+ this.dnsResolver = dnsResolver != null ? dnsResolver :
+ SystemDefaultDnsResolver.INSTANCE;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Lookup<ConnectionSocketFactory> getSocketFactoryRegistry(final HttpContext context) {
+ Lookup<ConnectionSocketFactory> reg = (Lookup<ConnectionSocketFactory>) context.getAttribute(
+ SOCKET_FACTORY_REGISTRY);
+ if (reg == null) {
+ reg = this.socketFactoryRegistry;
+ }
+ return reg;
+ }
+
+ public void connect(
+ final ManagedHttpClientConnection conn,
+ final HttpHost host,
+ final InetSocketAddress localAddress,
+ final int connectTimeout,
+ final SocketConfig socketConfig,
+ final HttpContext context) throws IOException {
+ final Lookup<ConnectionSocketFactory> registry = getSocketFactoryRegistry(context);
+ final ConnectionSocketFactory sf = registry.lookup(host.getSchemeName());
+ if (sf == null) {
+ throw new UnsupportedSchemeException(host.getSchemeName() +
+ " protocol is not supported");
+ }
+ final InetAddress[] addresses = this.dnsResolver.resolve(host.getHostName());
+ final int port = this.schemePortResolver.resolve(host);
+ for (int i = 0; i < addresses.length; i++) {
+ final InetAddress address = addresses[i];
+ final boolean last = i == addresses.length - 1;
+
+ Socket sock = sf.createSocket(context);
+ sock.setSoTimeout(socketConfig.getSoTimeout());
+ sock.setReuseAddress(socketConfig.isSoReuseAddress());
+ sock.setTcpNoDelay(socketConfig.isTcpNoDelay());
+ sock.setKeepAlive(socketConfig.isSoKeepAlive());
+ final int linger = socketConfig.getSoLinger();
+ if (linger >= 0) {
+ sock.setSoLinger(linger > 0, linger);
+ }
+ conn.bind(sock);
+
+ final InetSocketAddress remoteAddress = new InetSocketAddress(address, port);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connecting to " + remoteAddress);
+ }
+ try {
+ sock = sf.connectSocket(
+ connectTimeout, sock, host, remoteAddress, localAddress, context);
+ conn.bind(sock);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection established " + conn);
+ }
+ return;
+ } catch (final SocketTimeoutException ex) {
+ if (last) {
+ throw new ConnectTimeoutException(ex, host, addresses);
+ }
+ } catch (final ConnectException ex) {
+ if (last) {
+ final String msg = ex.getMessage();
+ if ("Connection timed out".equals(msg)) {
+ throw new ConnectTimeoutException(ex, host, addresses);
+ } else {
+ throw new HttpHostConnectException(ex, host, addresses);
+ }
+ }
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connect to " + remoteAddress + " timed out. " +
+ "Connection will be retried using another IP address");
+ }
+ }
+ }
+
+ public void upgrade(
+ final ManagedHttpClientConnection conn,
+ final HttpHost host,
+ final HttpContext context) throws IOException {
+ final HttpClientContext clientContext = HttpClientContext.adapt(context);
+ final Lookup<ConnectionSocketFactory> registry = getSocketFactoryRegistry(clientContext);
+ final ConnectionSocketFactory sf = registry.lookup(host.getSchemeName());
+ if (sf == null) {
+ throw new UnsupportedSchemeException(host.getSchemeName() +
+ " protocol is not supported");
+ }
+ if (!(sf instanceof LayeredConnectionSocketFactory)) {
+ throw new UnsupportedSchemeException(host.getSchemeName() +
+ " protocol does not support connection upgrade");
+ }
+ final LayeredConnectionSocketFactory lsf = (LayeredConnectionSocketFactory) sf;
+ Socket sock = conn.getSocket();
+ final int port = this.schemePortResolver.resolve(host);
+ sock = lsf.createLayeredSocket(sock, host.getHostName(), port, context);
+ conn.bind(sock);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpConnPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpConnPool.java
new file mode 100644
index 000000000..e10bd6cf6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpConnPool.java
@@ -0,0 +1,84 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.pool.AbstractConnPool;
+import ch.boye.httpclientandroidlib.pool.ConnFactory;
+
+/**
+ * @since 4.2
+ *
+ * @deprecated (4.3) no longer used.
+ */
+@Deprecated
+class HttpConnPool extends AbstractConnPool<HttpRoute, OperatedClientConnection, HttpPoolEntry> {
+
+ private static final AtomicLong COUNTER = new AtomicLong();
+
+ public HttpClientAndroidLog log;
+ private final long timeToLive;
+ private final TimeUnit tunit;
+
+ public HttpConnPool(final HttpClientAndroidLog log,
+ final ClientConnectionOperator connOperator,
+ final int defaultMaxPerRoute, final int maxTotal,
+ final long timeToLive, final TimeUnit tunit) {
+ super(new InternalConnFactory(connOperator), defaultMaxPerRoute, maxTotal);
+ this.log = log;
+ this.timeToLive = timeToLive;
+ this.tunit = tunit;
+ }
+
+ @Override
+ protected HttpPoolEntry createEntry(final HttpRoute route, final OperatedClientConnection conn) {
+ final String id = Long.toString(COUNTER.getAndIncrement());
+ return new HttpPoolEntry(this.log, id, route, conn, this.timeToLive, this.tunit);
+ }
+
+ static class InternalConnFactory implements ConnFactory<HttpRoute, OperatedClientConnection> {
+
+ private final ClientConnectionOperator connOperator;
+
+ InternalConnFactory(final ClientConnectionOperator connOperator) {
+ this.connOperator = connOperator;
+ }
+
+ public OperatedClientConnection create(final HttpRoute route) throws IOException {
+ return connOperator.createConnection();
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpPoolEntry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpPoolEntry.java
new file mode 100644
index 000000000..d04023126
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/HttpPoolEntry.java
@@ -0,0 +1,98 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.RouteTracker;
+import ch.boye.httpclientandroidlib.pool.PoolEntry;
+
+/**
+ * @since 4.2
+ *
+ * @deprecated (4.3) no longer used.
+ */
+@Deprecated
+class HttpPoolEntry extends PoolEntry<HttpRoute, OperatedClientConnection> {
+
+ public HttpClientAndroidLog log;
+ private final RouteTracker tracker;
+
+ public HttpPoolEntry(
+ final HttpClientAndroidLog log,
+ final String id,
+ final HttpRoute route,
+ final OperatedClientConnection conn,
+ final long timeToLive, final TimeUnit tunit) {
+ super(id, route, conn, timeToLive, tunit);
+ this.log = log;
+ this.tracker = new RouteTracker(route);
+ }
+
+ @Override
+ public boolean isExpired(final long now) {
+ final boolean expired = super.isExpired(now);
+ if (expired && this.log.isDebugEnabled()) {
+ this.log.debug("Connection " + this + " expired @ " + new Date(getExpiry()));
+ }
+ return expired;
+ }
+
+ RouteTracker getTracker() {
+ return this.tracker;
+ }
+
+ HttpRoute getPlannedRoute() {
+ return getRoute();
+ }
+
+ HttpRoute getEffectiveRoute() {
+ return this.tracker.toRoute();
+ }
+
+ @Override
+ public boolean isClosed() {
+ final OperatedClientConnection conn = getConnection();
+ return !conn.isOpen();
+ }
+
+ @Override
+ public void close() {
+ final OperatedClientConnection conn = getConnection();
+ try {
+ conn.close();
+ } catch (final IOException ex) {
+ this.log.debug("I/O error closing connection", ex);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/IdleConnectionHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/IdleConnectionHandler.java
new file mode 100644
index 000000000..cbcd5d04f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/IdleConnectionHandler.java
@@ -0,0 +1,181 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpConnection;
+
+// Currently only used by AbstractConnPool
+/**
+ * A helper class for connection managers to track idle connections.
+ *
+ * <p>This class is not synchronized.</p>
+ *
+ * @see ch.boye.httpclientandroidlib.conn.ClientConnectionManager#closeIdleConnections
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.1) no longer used
+ */
+@Deprecated
+public class IdleConnectionHandler {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /** Holds connections and the time they were added. */
+ private final Map<HttpConnection,TimeValues> connectionToTimes;
+
+
+ public IdleConnectionHandler() {
+ super();
+ connectionToTimes = new HashMap<HttpConnection,TimeValues>();
+ }
+
+ /**
+ * Registers the given connection with this handler. The connection will be held until
+ * {@link #remove} or {@link #closeIdleConnections} is called.
+ *
+ * @param connection the connection to add
+ *
+ * @see #remove
+ */
+ public void add(final HttpConnection connection, final long validDuration, final TimeUnit unit) {
+
+ final long timeAdded = System.currentTimeMillis();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Adding connection at: " + timeAdded);
+ }
+
+ connectionToTimes.put(connection, new TimeValues(timeAdded, validDuration, unit));
+ }
+
+ /**
+ * Removes the given connection from the list of connections to be closed when idle.
+ * This will return true if the connection is still valid, and false
+ * if the connection should be considered expired and not used.
+ *
+ * @param connection
+ * @return True if the connection is still valid.
+ */
+ public boolean remove(final HttpConnection connection) {
+ final TimeValues times = connectionToTimes.remove(connection);
+ if(times == null) {
+ log.warn("Removing a connection that never existed!");
+ return true;
+ } else {
+ return System.currentTimeMillis() <= times.timeExpires;
+ }
+ }
+
+ /**
+ * Removes all connections referenced by this handler.
+ */
+ public void removeAll() {
+ this.connectionToTimes.clear();
+ }
+
+ /**
+ * Closes connections that have been idle for at least the given amount of time.
+ *
+ * @param idleTime the minimum idle time, in milliseconds, for connections to be closed
+ */
+ public void closeIdleConnections(final long idleTime) {
+
+ // the latest time for which connections will be closed
+ final long idleTimeout = System.currentTimeMillis() - idleTime;
+
+ if (log.isDebugEnabled()) {
+ log.debug("Checking for connections, idle timeout: " + idleTimeout);
+ }
+
+ for (final Entry<HttpConnection, TimeValues> entry : connectionToTimes.entrySet()) {
+ final HttpConnection conn = entry.getKey();
+ final TimeValues times = entry.getValue();
+ final long connectionTime = times.timeAdded;
+ if (connectionTime <= idleTimeout) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing idle connection, connection time: " + connectionTime);
+ }
+ try {
+ conn.close();
+ } catch (final IOException ex) {
+ log.debug("I/O error closing connection", ex);
+ }
+ }
+ }
+ }
+
+
+ public void closeExpiredConnections() {
+ final long now = System.currentTimeMillis();
+ if (log.isDebugEnabled()) {
+ log.debug("Checking for expired connections, now: " + now);
+ }
+
+ for (final Entry<HttpConnection, TimeValues> entry : connectionToTimes.entrySet()) {
+ final HttpConnection conn = entry.getKey();
+ final TimeValues times = entry.getValue();
+ if(times.timeExpires <= now) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing connection, expired @: " + times.timeExpires);
+ }
+ try {
+ conn.close();
+ } catch (final IOException ex) {
+ log.debug("I/O error closing connection", ex);
+ }
+ }
+ }
+ }
+
+ private static class TimeValues {
+ private final long timeAdded;
+ private final long timeExpires;
+
+ /**
+ * @param now The current time in milliseconds
+ * @param validDuration The duration this connection is valid for
+ * @param validUnit The unit of time the duration is specified in.
+ */
+ TimeValues(final long now, final long validDuration, final TimeUnit validUnit) {
+ this.timeAdded = now;
+ if(validDuration > 0) {
+ this.timeExpires = now + validUnit.toMillis(validDuration);
+ } else {
+ this.timeExpires = Long.MAX_VALUE;
+ }
+ }
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/InMemoryDnsResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/InMemoryDnsResolver.java
new file mode 100644
index 000000000..34f02b11b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/InMemoryDnsResolver.java
@@ -0,0 +1,94 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.conn.DnsResolver;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * In-memory {@link DnsResolver} implementation.
+ *
+ * @since 4.2
+ */
+public class InMemoryDnsResolver implements DnsResolver {
+
+ /** Logger associated to this class. */
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(InMemoryDnsResolver.class);
+
+ /**
+ * In-memory collection that will hold the associations between a host name
+ * and an array of InetAddress instances.
+ */
+ private final Map<String, InetAddress[]> dnsMap;
+
+ /**
+ * Builds a DNS resolver that will resolve the host names against a
+ * collection held in-memory.
+ */
+ public InMemoryDnsResolver() {
+ dnsMap = new ConcurrentHashMap<String, InetAddress[]>();
+ }
+
+ /**
+ * Associates the given array of IP addresses to the given host in this DNS overrider.
+ * The IP addresses are assumed to be already resolved.
+ *
+ * @param host
+ * The host name to be associated with the given IP.
+ * @param ips
+ * array of IP addresses to be resolved by this DNS overrider to the given
+ * host name.
+ */
+ public void add(final String host, final InetAddress... ips) {
+ Args.notNull(host, "Host name");
+ Args.notNull(ips, "Array of IP addresses");
+ dnsMap.put(host, ips);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InetAddress[] resolve(final String host) throws UnknownHostException {
+ final InetAddress[] resolvedAddresses = dnsMap.get(host);
+ if (log.isInfoEnabled()) {
+ log.info("Resolving " + host + " to " + Arrays.deepToString(resolvedAddresses));
+ }
+ if(resolvedAddresses == null){
+ throw new UnknownHostException(host + " cannot be resolved");
+ }
+ return resolvedAddresses;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingInputStream.java
new file mode 100644
index 000000000..0c117395c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingInputStream.java
@@ -0,0 +1,145 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Internal class.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+class LoggingInputStream extends InputStream {
+
+ private final InputStream in;
+ private final Wire wire;
+
+ public LoggingInputStream(final InputStream in, final Wire wire) {
+ super();
+ this.in = in;
+ this.wire = wire;
+ }
+
+ @Override
+ public int read() throws IOException {
+ try {
+ final int b = in.read();
+ if (b == -1) {
+ wire.input("end of stream");
+ } else {
+ wire.input(b);
+ }
+ return b;
+ } catch (IOException ex) {
+ wire.input("[read] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public int read(final byte[] b) throws IOException {
+ try {
+ final int bytesRead = in.read(b);
+ if (bytesRead == -1) {
+ wire.input("end of stream");
+ } else if (bytesRead > 0) {
+ wire.input(b, 0, bytesRead);
+ }
+ return bytesRead;
+ } catch (IOException ex) {
+ wire.input("[read] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ try {
+ final int bytesRead = in.read(b, off, len);
+ if (bytesRead == -1) {
+ wire.input("end of stream");
+ } else if (bytesRead > 0) {
+ wire.input(b, off, bytesRead);
+ }
+ return bytesRead;
+ } catch (IOException ex) {
+ wire.input("[read] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ try {
+ return super.skip(n);
+ } catch (IOException ex) {
+ wire.input("[skip] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ try {
+ return in.available();
+ } catch (IOException ex) {
+ wire.input("[available] I/O error : " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public void mark(final int readlimit) {
+ super.mark(readlimit);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ super.reset();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ in.close();
+ } catch (IOException ex) {
+ wire.input("[close] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingManagedHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingManagedHttpClientConnection.java
new file mode 100644
index 000000000..5b06179c0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingManagedHttpClientConnection.java
@@ -0,0 +1,132 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+
+@NotThreadSafe
+class LoggingManagedHttpClientConnection extends DefaultManagedHttpClientConnection {
+
+ public HttpClientAndroidLog log;
+ private final HttpClientAndroidLog headerlog;
+ private final Wire wire;
+
+ public LoggingManagedHttpClientConnection(
+ final String id,
+ final HttpClientAndroidLog log,
+ final HttpClientAndroidLog headerlog,
+ final HttpClientAndroidLog wirelog,
+ final int buffersize,
+ final int fragmentSizeHint,
+ final CharsetDecoder chardecoder,
+ final CharsetEncoder charencoder,
+ final MessageConstraints constraints,
+ final ContentLengthStrategy incomingContentStrategy,
+ final ContentLengthStrategy outgoingContentStrategy,
+ final HttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+ final HttpMessageParserFactory<HttpResponse> responseParserFactory) {
+ super(id, buffersize, fragmentSizeHint, chardecoder, charencoder,
+ constraints, incomingContentStrategy, outgoingContentStrategy,
+ requestWriterFactory, responseParserFactory);
+ this.log = log;
+ this.headerlog = headerlog;
+ this.wire = new Wire(wirelog, id);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(getId() + ": Close connection");
+ }
+ super.close();
+ }
+
+ @Override
+ public void shutdown() throws IOException {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(getId() + ": Shutdown connection");
+ }
+ super.shutdown();
+ }
+
+ @Override
+ protected InputStream getSocketInputStream(final Socket socket) throws IOException {
+ InputStream in = super.getSocketInputStream(socket);
+ if (this.wire.enabled()) {
+ in = new LoggingInputStream(in, this.wire);
+ }
+ return in;
+ }
+
+ @Override
+ protected OutputStream getSocketOutputStream(final Socket socket) throws IOException {
+ OutputStream out = super.getSocketOutputStream(socket);
+ if (this.wire.enabled()) {
+ out = new LoggingOutputStream(out, this.wire);
+ }
+ return out;
+ }
+
+ @Override
+ protected void onResponseReceived(final HttpResponse response) {
+ if (response != null && this.headerlog.isDebugEnabled()) {
+ this.headerlog.debug(getId() + " << " + response.getStatusLine().toString());
+ final Header[] headers = response.getAllHeaders();
+ for (final Header header : headers) {
+ this.headerlog.debug(getId() + " << " + header.toString());
+ }
+ }
+ }
+
+ @Override
+ protected void onRequestSubmitted(final HttpRequest request) {
+ if (request != null && this.headerlog.isDebugEnabled()) {
+ this.headerlog.debug(getId() + " >> " + request.getRequestLine().toString());
+ final Header[] headers = request.getAllHeaders();
+ for (final Header header : headers) {
+ this.headerlog.debug(getId() + " >> " + header.toString());
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingOutputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingOutputStream.java
new file mode 100644
index 000000000..86c47b502
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingOutputStream.java
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Internal class.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+class LoggingOutputStream extends OutputStream {
+
+ private final OutputStream out;
+ private final Wire wire;
+
+ public LoggingOutputStream(final OutputStream out, final Wire wire) {
+ super();
+ this.out = out;
+ this.wire = wire;
+ }
+
+ @Override
+ public void write(final int b) throws IOException {
+ try {
+ wire.output(b);
+ } catch (IOException ex) {
+ wire.output("[write] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public void write(final byte[] b) throws IOException {
+ try {
+ wire.output(b);
+ out.write(b);
+ } catch (IOException ex) {
+ wire.output("[write] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ try {
+ wire.output(b, off, len);
+ out.write(b, off, len);
+ } catch (IOException ex) {
+ wire.output("[write] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ try {
+ out.flush();
+ } catch (IOException ex) {
+ wire.output("[flush] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ out.close();
+ } catch (IOException ex) {
+ wire.output("[close] I/O error: " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java
new file mode 100644
index 000000000..95617206e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java
@@ -0,0 +1,138 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.io.EofSensor;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Logs all data read to the wire LOG.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) no longer used.
+ */
+@Immutable
+@Deprecated
+public class LoggingSessionInputBuffer implements SessionInputBuffer, EofSensor {
+
+ /** Original session input buffer. */
+ private final SessionInputBuffer in;
+
+ private final EofSensor eofSensor;
+
+ /** The wire log to use for writing. */
+ private final Wire wire;
+
+ private final String charset;
+
+ /**
+ * Create an instance that wraps the specified session input buffer.
+ * @param in The session input buffer.
+ * @param wire The wire log to use.
+ * @param charset protocol charset, <code>ASCII</code> if <code>null</code>
+ */
+ public LoggingSessionInputBuffer(
+ final SessionInputBuffer in, final Wire wire, final String charset) {
+ super();
+ this.in = in;
+ this.eofSensor = in instanceof EofSensor ? (EofSensor) in : null;
+ this.wire = wire;
+ this.charset = charset != null ? charset : Consts.ASCII.name();
+ }
+
+ public LoggingSessionInputBuffer(final SessionInputBuffer in, final Wire wire) {
+ this(in, wire, null);
+ }
+
+ public boolean isDataAvailable(final int timeout) throws IOException {
+ return this.in.isDataAvailable(timeout);
+ }
+
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ final int l = this.in.read(b, off, len);
+ if (this.wire.enabled() && l > 0) {
+ this.wire.input(b, off, l);
+ }
+ return l;
+ }
+
+ public int read() throws IOException {
+ final int l = this.in.read();
+ if (this.wire.enabled() && l != -1) {
+ this.wire.input(l);
+ }
+ return l;
+ }
+
+ public int read(final byte[] b) throws IOException {
+ final int l = this.in.read(b);
+ if (this.wire.enabled() && l > 0) {
+ this.wire.input(b, 0, l);
+ }
+ return l;
+ }
+
+ public String readLine() throws IOException {
+ final String s = this.in.readLine();
+ if (this.wire.enabled() && s != null) {
+ final String tmp = s + "\r\n";
+ this.wire.input(tmp.getBytes(this.charset));
+ }
+ return s;
+ }
+
+ public int readLine(final CharArrayBuffer buffer) throws IOException {
+ final int l = this.in.readLine(buffer);
+ if (this.wire.enabled() && l >= 0) {
+ final int pos = buffer.length() - l;
+ final String s = new String(buffer.buffer(), pos, l);
+ final String tmp = s + "\r\n";
+ this.wire.input(tmp.getBytes(this.charset));
+ }
+ return l;
+ }
+
+ public HttpTransportMetrics getMetrics() {
+ return this.in.getMetrics();
+ }
+
+ public boolean isEof() {
+ if (this.eofSensor != null) {
+ return this.eofSensor.isEof();
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java
new file mode 100644
index 000000000..bf1100b4e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java
@@ -0,0 +1,118 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Logs all data written to the wire LOG.
+ * @since 4.0
+ * @deprecated (4.3) no longer used.
+ */
+@Immutable
+@Deprecated
+public class LoggingSessionOutputBuffer implements SessionOutputBuffer {
+
+ /** Original data transmitter. */
+ private final SessionOutputBuffer out;
+
+ /** The wire log to use. */
+ private final Wire wire;
+
+ private final String charset;
+
+ /**
+ * Create an instance that wraps the specified session output buffer.
+ * @param out The session output buffer.
+ * @param wire The Wire log to use.
+ * @param charset protocol charset, <code>ASCII</code> if <code>null</code>
+ */
+ public LoggingSessionOutputBuffer(
+ final SessionOutputBuffer out, final Wire wire, final String charset) {
+ super();
+ this.out = out;
+ this.wire = wire;
+ this.charset = charset != null ? charset : Consts.ASCII.name();
+ }
+
+ public LoggingSessionOutputBuffer(final SessionOutputBuffer out, final Wire wire) {
+ this(out, wire, null);
+ }
+
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ this.out.write(b, off, len);
+ if (this.wire.enabled()) {
+ this.wire.output(b, off, len);
+ }
+ }
+
+ public void write(final int b) throws IOException {
+ this.out.write(b);
+ if (this.wire.enabled()) {
+ this.wire.output(b);
+ }
+ }
+
+ public void write(final byte[] b) throws IOException {
+ this.out.write(b);
+ if (this.wire.enabled()) {
+ this.wire.output(b);
+ }
+ }
+
+ public void flush() throws IOException {
+ this.out.flush();
+ }
+
+ public void writeLine(final CharArrayBuffer buffer) throws IOException {
+ this.out.writeLine(buffer);
+ if (this.wire.enabled()) {
+ final String s = new String(buffer.buffer(), 0, buffer.length());
+ final String tmp = s + "\r\n";
+ this.wire.output(tmp.getBytes(this.charset));
+ }
+ }
+
+ public void writeLine(final String s) throws IOException {
+ this.out.writeLine(s);
+ if (this.wire.enabled()) {
+ final String tmp = s + "\r\n";
+ this.wire.output(tmp.getBytes(this.charset));
+ }
+ }
+
+ public HttpTransportMetrics getMetrics() {
+ return this.out.getMetrics();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedClientConnectionImpl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedClientConnectionImpl.java
new file mode 100644
index 000000000..d1db2d8eb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedClientConnectionImpl.java
@@ -0,0 +1,461 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.RouteTracker;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link ManagedHttpClientConnectionFactory}.
+ */
+@Deprecated
+@NotThreadSafe
+class ManagedClientConnectionImpl implements ManagedClientConnection {
+
+ private final ClientConnectionManager manager;
+ private final ClientConnectionOperator operator;
+ private volatile HttpPoolEntry poolEntry;
+ private volatile boolean reusable;
+ private volatile long duration;
+
+ ManagedClientConnectionImpl(
+ final ClientConnectionManager manager,
+ final ClientConnectionOperator operator,
+ final HttpPoolEntry entry) {
+ super();
+ Args.notNull(manager, "Connection manager");
+ Args.notNull(operator, "Connection operator");
+ Args.notNull(entry, "HTTP pool entry");
+ this.manager = manager;
+ this.operator = operator;
+ this.poolEntry = entry;
+ this.reusable = false;
+ this.duration = Long.MAX_VALUE;
+ }
+
+ public String getId() {
+ return null;
+ }
+
+ HttpPoolEntry getPoolEntry() {
+ return this.poolEntry;
+ }
+
+ HttpPoolEntry detach() {
+ final HttpPoolEntry local = this.poolEntry;
+ this.poolEntry = null;
+ return local;
+ }
+
+ public ClientConnectionManager getManager() {
+ return this.manager;
+ }
+
+ private OperatedClientConnection getConnection() {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local == null) {
+ return null;
+ }
+ return local.getConnection();
+ }
+
+ private OperatedClientConnection ensureConnection() {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local == null) {
+ throw new ConnectionShutdownException();
+ }
+ return local.getConnection();
+ }
+
+ private HttpPoolEntry ensurePoolEntry() {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local == null) {
+ throw new ConnectionShutdownException();
+ }
+ return local;
+ }
+
+ public void close() throws IOException {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local != null) {
+ final OperatedClientConnection conn = local.getConnection();
+ local.getTracker().reset();
+ conn.close();
+ }
+ }
+
+ public void shutdown() throws IOException {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local != null) {
+ final OperatedClientConnection conn = local.getConnection();
+ local.getTracker().reset();
+ conn.shutdown();
+ }
+ }
+
+ public boolean isOpen() {
+ final OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ return conn.isOpen();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isStale() {
+ final OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ return conn.isStale();
+ } else {
+ return true;
+ }
+ }
+
+ public void setSocketTimeout(final int timeout) {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.setSocketTimeout(timeout);
+ }
+
+ public int getSocketTimeout() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getSocketTimeout();
+ }
+
+ public HttpConnectionMetrics getMetrics() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getMetrics();
+ }
+
+ public void flush() throws IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.flush();
+ }
+
+ public boolean isResponseAvailable(final int timeout) throws IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.isResponseAvailable(timeout);
+ }
+
+ public void receiveResponseEntity(
+ final HttpResponse response) throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.receiveResponseEntity(response);
+ }
+
+ public HttpResponse receiveResponseHeader() throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.receiveResponseHeader();
+ }
+
+ public void sendRequestEntity(
+ final HttpEntityEnclosingRequest request) throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.sendRequestEntity(request);
+ }
+
+ public void sendRequestHeader(
+ final HttpRequest request) throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.sendRequestHeader(request);
+ }
+
+ public InetAddress getLocalAddress() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getLocalAddress();
+ }
+
+ public int getLocalPort() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getLocalPort();
+ }
+
+ public InetAddress getRemoteAddress() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getRemoteAddress();
+ }
+
+ public int getRemotePort() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getRemotePort();
+ }
+
+ public boolean isSecure() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.isSecure();
+ }
+
+ public void bind(final Socket socket) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Socket getSocket() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getSocket();
+ }
+
+ public SSLSession getSSLSession() {
+ final OperatedClientConnection conn = ensureConnection();
+ SSLSession result = null;
+ final Socket sock = conn.getSocket();
+ if (sock instanceof SSLSocket) {
+ result = ((SSLSocket)sock).getSession();
+ }
+ return result;
+ }
+
+ public Object getAttribute(final String id) {
+ final OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).getAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public Object removeAttribute(final String id) {
+ final OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).removeAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ final OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ ((HttpContext) conn).setAttribute(id, obj);
+ }
+ }
+
+ public HttpRoute getRoute() {
+ final HttpPoolEntry local = ensurePoolEntry();
+ return local.getEffectiveRoute();
+ }
+
+ public void open(
+ final HttpRoute route,
+ final HttpContext context,
+ final HttpParams params) throws IOException {
+ Args.notNull(route, "Route");
+ Args.notNull(params, "HTTP parameters");
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(!tracker.isConnected(), "Connection already open");
+ conn = this.poolEntry.getConnection();
+ }
+
+ final HttpHost proxy = route.getProxyHost();
+ this.operator.openConnection(
+ conn,
+ (proxy != null) ? proxy : route.getTargetHost(),
+ route.getLocalAddress(),
+ context, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ if (proxy == null) {
+ tracker.connectTarget(conn.isSecure());
+ } else {
+ tracker.connectProxy(proxy, conn.isSecure());
+ }
+ }
+ }
+
+ public void tunnelTarget(
+ final boolean secure, final HttpParams params) throws IOException {
+ Args.notNull(params, "HTTP parameters");
+ final HttpHost target;
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(tracker.isConnected(), "Connection not open");
+ Asserts.check(!tracker.isTunnelled(), "Connection is already tunnelled");
+ target = tracker.getTargetHost();
+ conn = this.poolEntry.getConnection();
+ }
+
+ conn.update(null, target, secure, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.tunnelTarget(secure);
+ }
+ }
+
+ public void tunnelProxy(
+ final HttpHost next, final boolean secure, final HttpParams params) throws IOException {
+ Args.notNull(next, "Next proxy");
+ Args.notNull(params, "HTTP parameters");
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(tracker.isConnected(), "Connection not open");
+ conn = this.poolEntry.getConnection();
+ }
+
+ conn.update(null, next, secure, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.tunnelProxy(next, secure);
+ }
+ }
+
+ public void layerProtocol(
+ final HttpContext context, final HttpParams params) throws IOException {
+ Args.notNull(params, "HTTP parameters");
+ final HttpHost target;
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(tracker.isConnected(), "Connection not open");
+ Asserts.check(tracker.isTunnelled(), "Protocol layering without a tunnel not supported");
+ Asserts.check(!tracker.isLayered(), "Multiple protocol layering not supported");
+ target = tracker.getTargetHost();
+ conn = this.poolEntry.getConnection();
+ }
+ this.operator.updateSecureConnection(conn, target, context, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.layerProtocol(conn.isSecure());
+ }
+ }
+
+ public Object getState() {
+ final HttpPoolEntry local = ensurePoolEntry();
+ return local.getState();
+ }
+
+ public void setState(final Object state) {
+ final HttpPoolEntry local = ensurePoolEntry();
+ local.setState(state);
+ }
+
+ public void markReusable() {
+ this.reusable = true;
+ }
+
+ public void unmarkReusable() {
+ this.reusable = false;
+ }
+
+ public boolean isMarkedReusable() {
+ return this.reusable;
+ }
+
+ public void setIdleDuration(final long duration, final TimeUnit unit) {
+ if(duration > 0) {
+ this.duration = unit.toMillis(duration);
+ } else {
+ this.duration = -1;
+ }
+ }
+
+ public void releaseConnection() {
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ return;
+ }
+ this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
+ this.poolEntry = null;
+ }
+ }
+
+ public void abortConnection() {
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ return;
+ }
+ this.reusable = false;
+ final OperatedClientConnection conn = this.poolEntry.getConnection();
+ try {
+ conn.shutdown();
+ } catch (final IOException ignore) {
+ }
+ this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
+ this.poolEntry = null;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedHttpClientConnectionFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedHttpClientConnectionFactory.java
new file mode 100644
index 000000000..51b3844f9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ManagedHttpClientConnectionFactory.java
@@ -0,0 +1,121 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+import java.util.concurrent.atomic.AtomicLong;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.conn.HttpConnectionFactory;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.impl.io.DefaultHttpRequestWriterFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+
+/**
+ * Factory for {@link ManagedHttpClientConnection} instances.
+ * @since 4.3
+ */
+@Immutable
+public class ManagedHttpClientConnectionFactory
+ implements HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> {
+
+ private static final AtomicLong COUNTER = new AtomicLong();
+
+ public static final ManagedHttpClientConnectionFactory INSTANCE = new ManagedHttpClientConnectionFactory();
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(DefaultManagedHttpClientConnection.class);
+ public HttpClientAndroidLog headerlog = new HttpClientAndroidLog("ch.boye.httpclientandroidlib.headers");
+ public HttpClientAndroidLog wirelog = new HttpClientAndroidLog("ch.boye.httpclientandroidlib.wire");
+
+ private final HttpMessageWriterFactory<HttpRequest> requestWriterFactory;
+ private final HttpMessageParserFactory<HttpResponse> responseParserFactory;
+
+ public ManagedHttpClientConnectionFactory(
+ final HttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+ final HttpMessageParserFactory<HttpResponse> responseParserFactory) {
+ super();
+ this.requestWriterFactory = requestWriterFactory != null ? requestWriterFactory :
+ DefaultHttpRequestWriterFactory.INSTANCE;
+ this.responseParserFactory = responseParserFactory != null ? responseParserFactory :
+ DefaultHttpResponseParserFactory.INSTANCE;
+ }
+
+ public ManagedHttpClientConnectionFactory(
+ final HttpMessageParserFactory<HttpResponse> responseParserFactory) {
+ this(null, responseParserFactory);
+ }
+
+ public ManagedHttpClientConnectionFactory() {
+ this(null, null);
+ }
+
+ public ManagedHttpClientConnection create(final HttpRoute route, final ConnectionConfig config) {
+ final ConnectionConfig cconfig = config != null ? config : ConnectionConfig.DEFAULT;
+ CharsetDecoder chardecoder = null;
+ CharsetEncoder charencoder = null;
+ final Charset charset = cconfig.getCharset();
+ final CodingErrorAction malformedInputAction = cconfig.getMalformedInputAction() != null ?
+ cconfig.getMalformedInputAction() : CodingErrorAction.REPORT;
+ final CodingErrorAction unmappableInputAction = cconfig.getUnmappableInputAction() != null ?
+ cconfig.getUnmappableInputAction() : CodingErrorAction.REPORT;
+ if (charset != null) {
+ chardecoder = charset.newDecoder();
+ chardecoder.onMalformedInput(malformedInputAction);
+ chardecoder.onUnmappableCharacter(unmappableInputAction);
+ charencoder = charset.newEncoder();
+ charencoder.onMalformedInput(malformedInputAction);
+ charencoder.onUnmappableCharacter(unmappableInputAction);
+ }
+ final String id = "http-outgoing-" + Long.toString(COUNTER.getAndIncrement());
+ return new LoggingManagedHttpClientConnection(
+ id,
+ log,
+ headerlog,
+ wirelog,
+ cconfig.getBufferSize(),
+ cconfig.getFragmentSizeHint(),
+ chardecoder,
+ charencoder,
+ cconfig.getMessageConstraints(),
+ null,
+ null,
+ requestWriterFactory,
+ responseParserFactory);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingClientConnectionManager.java
new file mode 100644
index 000000000..f9685b81e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingClientConnectionManager.java
@@ -0,0 +1,328 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
+import ch.boye.httpclientandroidlib.conn.DnsResolver;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.pool.ConnPoolControl;
+import ch.boye.httpclientandroidlib.pool.PoolStats;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Manages a pool of {@link ch.boye.httpclientandroidlib.conn.OperatedClientConnection}
+ * and is able to service connection requests from multiple execution threads.
+ * Connections are pooled on a per route basis. A request for a route which
+ * already the manager has persistent connections for available in the pool
+ * will be services by leasing a connection from the pool rather than
+ * creating a brand new connection.
+ * <p>
+ * PoolingConnectionManager maintains a maximum limit of connection on
+ * a per route basis and in total. Per default this implementation will
+ * create no more than than 2 concurrent connections per given route
+ * and no more 20 connections in total. For many real-world applications
+ * these limits may prove too constraining, especially if they use HTTP
+ * as a transport protocol for their services. Connection limits, however,
+ * can be adjusted using HTTP parameters.
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use {@link PoolingHttpClientConnectionManager}.
+ */
+@Deprecated
+@ThreadSafe
+public class PoolingClientConnectionManager implements ClientConnectionManager, ConnPoolControl<HttpRoute> {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final SchemeRegistry schemeRegistry;
+
+ private final HttpConnPool pool;
+
+ private final ClientConnectionOperator operator;
+
+ /** the custom-configured DNS lookup mechanism. */
+ private final DnsResolver dnsResolver;
+
+ public PoolingClientConnectionManager(final SchemeRegistry schreg) {
+ this(schreg, -1, TimeUnit.MILLISECONDS);
+ }
+
+ public PoolingClientConnectionManager(final SchemeRegistry schreg,final DnsResolver dnsResolver) {
+ this(schreg, -1, TimeUnit.MILLISECONDS,dnsResolver);
+ }
+
+ public PoolingClientConnectionManager() {
+ this(SchemeRegistryFactory.createDefault());
+ }
+
+ public PoolingClientConnectionManager(
+ final SchemeRegistry schemeRegistry,
+ final long timeToLive, final TimeUnit tunit) {
+ this(schemeRegistry, timeToLive, tunit, new SystemDefaultDnsResolver());
+ }
+
+ public PoolingClientConnectionManager(final SchemeRegistry schemeRegistry,
+ final long timeToLive, final TimeUnit tunit,
+ final DnsResolver dnsResolver) {
+ super();
+ Args.notNull(schemeRegistry, "Scheme registry");
+ Args.notNull(dnsResolver, "DNS resolver");
+ this.schemeRegistry = schemeRegistry;
+ this.dnsResolver = dnsResolver;
+ this.operator = createConnectionOperator(schemeRegistry);
+ this.pool = new HttpConnPool(this.log, this.operator, 2, 20, timeToLive, tunit);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Hook for creating the connection operator.
+ * It is called by the constructor.
+ * Derived classes can override this method to change the
+ * instantiation of the operator.
+ * The default implementation here instantiates
+ * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
+ *
+ * @param schreg the scheme registry.
+ *
+ * @return the connection operator to use
+ */
+ protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry schreg) {
+ return new DefaultClientConnectionOperator(schreg, this.dnsResolver);
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ return this.schemeRegistry;
+ }
+
+ private String format(final HttpRoute route, final Object state) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("[route: ").append(route).append("]");
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ private String formatStats(final HttpRoute route) {
+ final StringBuilder buf = new StringBuilder();
+ final PoolStats totals = this.pool.getTotalStats();
+ final PoolStats stats = this.pool.getStats(route);
+ buf.append("[total kept alive: ").append(totals.getAvailable()).append("; ");
+ buf.append("route allocated: ").append(stats.getLeased() + stats.getAvailable());
+ buf.append(" of ").append(stats.getMax()).append("; ");
+ buf.append("total allocated: ").append(totals.getLeased() + totals.getAvailable());
+ buf.append(" of ").append(totals.getMax()).append("]");
+ return buf.toString();
+ }
+
+ private String format(final HttpPoolEntry entry) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("[id: ").append(entry.getId()).append("]");
+ buf.append("[route: ").append(entry.getRoute()).append("]");
+ final Object state = entry.getState();
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ public ClientConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+ Args.notNull(route, "HTTP route");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection request: " + format(route, state) + formatStats(route));
+ }
+ final Future<HttpPoolEntry> future = this.pool.lease(route, state);
+
+ return new ClientConnectionRequest() {
+
+ public void abortRequest() {
+ future.cancel(true);
+ }
+
+ public ManagedClientConnection getConnection(
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+ return leaseConnection(future, timeout, tunit);
+ }
+
+ };
+
+ }
+
+ ManagedClientConnection leaseConnection(
+ final Future<HttpPoolEntry> future,
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+ final HttpPoolEntry entry;
+ try {
+ entry = future.get(timeout, tunit);
+ if (entry == null || future.isCancelled()) {
+ throw new InterruptedException();
+ }
+ Asserts.check(entry.getConnection() != null, "Pool entry with no connection");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ return new ManagedClientConnectionImpl(this, this.operator, entry);
+ } catch (final ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ if (cause == null) {
+ cause = ex;
+ }
+ this.log.error("Unexpected exception leasing connection from pool", cause);
+ // Should never happen
+ throw new InterruptedException();
+ } catch (final TimeoutException ex) {
+ throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
+ }
+ }
+
+ public void releaseConnection(
+ final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) {
+
+ Args.check(conn instanceof ManagedClientConnectionImpl, "Connection class mismatch, " +
+ "connection not obtained from this manager");
+ final ManagedClientConnectionImpl managedConn = (ManagedClientConnectionImpl) conn;
+ Asserts.check(managedConn.getManager() == this, "Connection not obtained from this manager");
+ synchronized (managedConn) {
+ final HttpPoolEntry entry = managedConn.detach();
+ if (entry == null) {
+ return;
+ }
+ try {
+ if (managedConn.isOpen() && !managedConn.isMarkedReusable()) {
+ try {
+ managedConn.shutdown();
+ } catch (final IOException iox) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("I/O exception shutting down released connection", iox);
+ }
+ }
+ }
+ // Only reusable connections can be kept alive
+ if (managedConn.isMarkedReusable()) {
+ entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS);
+ if (this.log.isDebugEnabled()) {
+ final String s;
+ if (keepalive > 0) {
+ s = "for " + keepalive + " " + tunit;
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
+ }
+ }
+ } finally {
+ this.pool.release(entry, managedConn.isMarkedReusable());
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ }
+ }
+
+ public void shutdown() {
+ this.log.debug("Connection manager is shutting down");
+ try {
+ this.pool.shutdown();
+ } catch (final IOException ex) {
+ this.log.debug("I/O exception shutting down connection manager", ex);
+ }
+ this.log.debug("Connection manager shut down");
+ }
+
+ public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit);
+ }
+ this.pool.closeIdle(idleTimeout, tunit);
+ }
+
+ public void closeExpiredConnections() {
+ this.log.debug("Closing expired connections");
+ this.pool.closeExpired();
+ }
+
+ public int getMaxTotal() {
+ return this.pool.getMaxTotal();
+ }
+
+ public void setMaxTotal(final int max) {
+ this.pool.setMaxTotal(max);
+ }
+
+ public int getDefaultMaxPerRoute() {
+ return this.pool.getDefaultMaxPerRoute();
+ }
+
+ public void setDefaultMaxPerRoute(final int max) {
+ this.pool.setDefaultMaxPerRoute(max);
+ }
+
+ public int getMaxPerRoute(final HttpRoute route) {
+ return this.pool.getMaxPerRoute(route);
+ }
+
+ public void setMaxPerRoute(final HttpRoute route, final int max) {
+ this.pool.setMaxPerRoute(route, max);
+ }
+
+ public PoolStats getTotalStats() {
+ return this.pool.getTotalStats();
+ }
+
+ public PoolStats getStats(final HttpRoute route) {
+ return this.pool.getStats(route);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingHttpClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingHttpClientConnectionManager.java
new file mode 100644
index 000000000..a2606b4e6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/PoolingHttpClientConnectionManager.java
@@ -0,0 +1,516 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.config.Lookup;
+import ch.boye.httpclientandroidlib.config.Registry;
+import ch.boye.httpclientandroidlib.config.RegistryBuilder;
+import ch.boye.httpclientandroidlib.config.SocketConfig;
+import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
+import ch.boye.httpclientandroidlib.conn.ConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.DnsResolver;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.HttpConnectionFactory;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.conn.ManagedHttpClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.socket.ConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.socket.PlainConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.conn.ssl.SSLConnectionSocketFactory;
+import ch.boye.httpclientandroidlib.pool.ConnFactory;
+import ch.boye.httpclientandroidlib.pool.ConnPoolControl;
+import ch.boye.httpclientandroidlib.pool.PoolStats;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * <tt>ClientConnectionPoolManager</tt> maintains a pool of
+ * {@link HttpClientConnection}s and is able to service connection requests
+ * from multiple execution threads. Connections are pooled on a per route
+ * basis. A request for a route which already the manager has persistent
+ * connections for available in the pool will be services by leasing
+ * a connection from the pool rather than creating a brand new connection.
+ * <p/>
+ * <tt>ClientConnectionPoolManager</tt> maintains a maximum limit of connection
+ * on a per route basis and in total. Per default this implementation will
+ * create no more than than 2 concurrent connections per given route
+ * and no more 20 connections in total. For many real-world applications
+ * these limits may prove too constraining, especially if they use HTTP
+ * as a transport protocol for their services. Connection limits, however,
+ * can be adjusted using {@link ConnPoolControl} methods.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public class PoolingHttpClientConnectionManager
+ implements HttpClientConnectionManager, ConnPoolControl<HttpRoute>, Closeable {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final ConfigData configData;
+ private final CPool pool;
+ private final HttpClientConnectionOperator connectionOperator;
+ private final AtomicBoolean isShutDown;
+
+ private static Registry<ConnectionSocketFactory> getDefaultRegistry() {
+ return RegistryBuilder.<ConnectionSocketFactory>create()
+ .register("http", PlainConnectionSocketFactory.getSocketFactory())
+ .register("https", SSLConnectionSocketFactory.getSocketFactory())
+ .build();
+ }
+
+ public PoolingHttpClientConnectionManager() {
+ this(getDefaultRegistry());
+ }
+
+ public PoolingHttpClientConnectionManager(final long timeToLive, final TimeUnit tunit) {
+ this(getDefaultRegistry(), null, null ,null, timeToLive, tunit);
+ }
+
+ public PoolingHttpClientConnectionManager(
+ final Registry<ConnectionSocketFactory> socketFactoryRegistry) {
+ this(socketFactoryRegistry, null, null);
+ }
+
+ public PoolingHttpClientConnectionManager(
+ final Registry<ConnectionSocketFactory> socketFactoryRegistry,
+ final DnsResolver dnsResolver) {
+ this(socketFactoryRegistry, null, dnsResolver);
+ }
+
+ public PoolingHttpClientConnectionManager(
+ final Registry<ConnectionSocketFactory> socketFactoryRegistry,
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory) {
+ this(socketFactoryRegistry, connFactory, null);
+ }
+
+ public PoolingHttpClientConnectionManager(
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory) {
+ this(getDefaultRegistry(), connFactory, null);
+ }
+
+ public PoolingHttpClientConnectionManager(
+ final Registry<ConnectionSocketFactory> socketFactoryRegistry,
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,
+ final DnsResolver dnsResolver) {
+ this(socketFactoryRegistry, connFactory, null, dnsResolver, -1, TimeUnit.MILLISECONDS);
+ }
+
+ public PoolingHttpClientConnectionManager(
+ final Registry<ConnectionSocketFactory> socketFactoryRegistry,
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,
+ final SchemePortResolver schemePortResolver,
+ final DnsResolver dnsResolver,
+ final long timeToLive, final TimeUnit tunit) {
+ super();
+ this.configData = new ConfigData();
+ this.pool = new CPool(
+ new InternalConnectionFactory(this.configData, connFactory), 2, 20, timeToLive, tunit);
+ this.connectionOperator = new HttpClientConnectionOperator(
+ socketFactoryRegistry, schemePortResolver, dnsResolver);
+ this.isShutDown = new AtomicBoolean(false);
+ }
+
+ PoolingHttpClientConnectionManager(
+ final CPool pool,
+ final Lookup<ConnectionSocketFactory> socketFactoryRegistry,
+ final SchemePortResolver schemePortResolver,
+ final DnsResolver dnsResolver) {
+ super();
+ this.configData = new ConfigData();
+ this.pool = pool;
+ this.connectionOperator = new HttpClientConnectionOperator(
+ socketFactoryRegistry, schemePortResolver, dnsResolver);
+ this.isShutDown = new AtomicBoolean(false);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ public void close() {
+ shutdown();
+ }
+
+ private String format(final HttpRoute route, final Object state) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("[route: ").append(route).append("]");
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ private String formatStats(final HttpRoute route) {
+ final StringBuilder buf = new StringBuilder();
+ final PoolStats totals = this.pool.getTotalStats();
+ final PoolStats stats = this.pool.getStats(route);
+ buf.append("[total kept alive: ").append(totals.getAvailable()).append("; ");
+ buf.append("route allocated: ").append(stats.getLeased() + stats.getAvailable());
+ buf.append(" of ").append(stats.getMax()).append("; ");
+ buf.append("total allocated: ").append(totals.getLeased() + totals.getAvailable());
+ buf.append(" of ").append(totals.getMax()).append("]");
+ return buf.toString();
+ }
+
+ private String format(final CPoolEntry entry) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("[id: ").append(entry.getId()).append("]");
+ buf.append("[route: ").append(entry.getRoute()).append("]");
+ final Object state = entry.getState();
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ public ConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+ Args.notNull(route, "HTTP route");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection request: " + format(route, state) + formatStats(route));
+ }
+ final Future<CPoolEntry> future = this.pool.lease(route, state, null);
+ return new ConnectionRequest() {
+
+ public boolean cancel() {
+ return future.cancel(true);
+ }
+
+ public HttpClientConnection get(
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException {
+ return leaseConnection(future, timeout, tunit);
+ }
+
+ };
+
+ }
+
+ protected HttpClientConnection leaseConnection(
+ final Future<CPoolEntry> future,
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException {
+ final CPoolEntry entry;
+ try {
+ entry = future.get(timeout, tunit);
+ if (entry == null || future.isCancelled()) {
+ throw new InterruptedException();
+ }
+ Asserts.check(entry.getConnection() != null, "Pool entry with no connection");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ return CPoolProxy.newProxy(entry);
+ } catch (final TimeoutException ex) {
+ throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
+ }
+ }
+
+ public void releaseConnection(
+ final HttpClientConnection managedConn,
+ final Object state,
+ final long keepalive, final TimeUnit tunit) {
+ Args.notNull(managedConn, "Managed connection");
+ synchronized (managedConn) {
+ final CPoolEntry entry = CPoolProxy.detach(managedConn);
+ if (entry == null) {
+ return;
+ }
+ final ManagedHttpClientConnection conn = entry.getConnection();
+ try {
+ if (conn.isOpen()) {
+ entry.setState(state);
+ entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS);
+ if (this.log.isDebugEnabled()) {
+ final String s;
+ if (keepalive > 0) {
+ s = "for " + (double) keepalive / 1000 + " seconds";
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
+ }
+ }
+ } finally {
+ this.pool.release(entry, conn.isOpen() && entry.isRouteComplete());
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ }
+ }
+ }
+
+ public void connect(
+ final HttpClientConnection managedConn,
+ final HttpRoute route,
+ final int connectTimeout,
+ final HttpContext context) throws IOException {
+ Args.notNull(managedConn, "Managed Connection");
+ Args.notNull(route, "HTTP route");
+ final ManagedHttpClientConnection conn;
+ synchronized (managedConn) {
+ final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
+ conn = entry.getConnection();
+ }
+ final HttpHost host;
+ if (route.getProxyHost() != null) {
+ host = route.getProxyHost();
+ } else {
+ host = route.getTargetHost();
+ }
+ final InetSocketAddress localAddress = route.getLocalSocketAddress();
+ SocketConfig socketConfig = this.configData.getSocketConfig(host);
+ if (socketConfig == null) {
+ socketConfig = this.configData.getDefaultSocketConfig();
+ }
+ if (socketConfig == null) {
+ socketConfig = SocketConfig.DEFAULT;
+ }
+ this.connectionOperator.connect(
+ conn, host, localAddress, connectTimeout, socketConfig, context);
+ }
+
+ public void upgrade(
+ final HttpClientConnection managedConn,
+ final HttpRoute route,
+ final HttpContext context) throws IOException {
+ Args.notNull(managedConn, "Managed Connection");
+ Args.notNull(route, "HTTP route");
+ final ManagedHttpClientConnection conn;
+ synchronized (managedConn) {
+ final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
+ conn = entry.getConnection();
+ }
+ this.connectionOperator.upgrade(conn, route.getTargetHost(), context);
+ }
+
+ public void routeComplete(
+ final HttpClientConnection managedConn,
+ final HttpRoute route,
+ final HttpContext context) throws IOException {
+ Args.notNull(managedConn, "Managed Connection");
+ Args.notNull(route, "HTTP route");
+ synchronized (managedConn) {
+ final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
+ entry.markRouteComplete();
+ }
+ }
+
+ public void shutdown() {
+ if (this.isShutDown.compareAndSet(false, true)) {
+ this.log.debug("Connection manager is shutting down");
+ try {
+ this.pool.shutdown();
+ } catch (final IOException ex) {
+ this.log.debug("I/O exception shutting down connection manager", ex);
+ }
+ this.log.debug("Connection manager shut down");
+ }
+ }
+
+ public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit);
+ }
+ this.pool.closeIdle(idleTimeout, tunit);
+ }
+
+ public void closeExpiredConnections() {
+ this.log.debug("Closing expired connections");
+ this.pool.closeExpired();
+ }
+
+ public int getMaxTotal() {
+ return this.pool.getMaxTotal();
+ }
+
+ public void setMaxTotal(final int max) {
+ this.pool.setMaxTotal(max);
+ }
+
+ public int getDefaultMaxPerRoute() {
+ return this.pool.getDefaultMaxPerRoute();
+ }
+
+ public void setDefaultMaxPerRoute(final int max) {
+ this.pool.setDefaultMaxPerRoute(max);
+ }
+
+ public int getMaxPerRoute(final HttpRoute route) {
+ return this.pool.getMaxPerRoute(route);
+ }
+
+ public void setMaxPerRoute(final HttpRoute route, final int max) {
+ this.pool.setMaxPerRoute(route, max);
+ }
+
+ public PoolStats getTotalStats() {
+ return this.pool.getTotalStats();
+ }
+
+ public PoolStats getStats(final HttpRoute route) {
+ return this.pool.getStats(route);
+ }
+
+ public SocketConfig getDefaultSocketConfig() {
+ return this.configData.getDefaultSocketConfig();
+ }
+
+ public void setDefaultSocketConfig(final SocketConfig defaultSocketConfig) {
+ this.configData.setDefaultSocketConfig(defaultSocketConfig);
+ }
+
+ public ConnectionConfig getDefaultConnectionConfig() {
+ return this.configData.getDefaultConnectionConfig();
+ }
+
+ public void setDefaultConnectionConfig(final ConnectionConfig defaultConnectionConfig) {
+ this.configData.setDefaultConnectionConfig(defaultConnectionConfig);
+ }
+
+ public SocketConfig getSocketConfig(final HttpHost host) {
+ return this.configData.getSocketConfig(host);
+ }
+
+ public void setSocketConfig(final HttpHost host, final SocketConfig socketConfig) {
+ this.configData.setSocketConfig(host, socketConfig);
+ }
+
+ public ConnectionConfig getConnectionConfig(final HttpHost host) {
+ return this.configData.getConnectionConfig(host);
+ }
+
+ public void setConnectionConfig(final HttpHost host, final ConnectionConfig connectionConfig) {
+ this.configData.setConnectionConfig(host, connectionConfig);
+ }
+
+ static class ConfigData {
+
+ private final Map<HttpHost, SocketConfig> socketConfigMap;
+ private final Map<HttpHost, ConnectionConfig> connectionConfigMap;
+ private volatile SocketConfig defaultSocketConfig;
+ private volatile ConnectionConfig defaultConnectionConfig;
+
+ ConfigData() {
+ super();
+ this.socketConfigMap = new ConcurrentHashMap<HttpHost, SocketConfig>();
+ this.connectionConfigMap = new ConcurrentHashMap<HttpHost, ConnectionConfig>();
+ }
+
+ public SocketConfig getDefaultSocketConfig() {
+ return this.defaultSocketConfig;
+ }
+
+ public void setDefaultSocketConfig(final SocketConfig defaultSocketConfig) {
+ this.defaultSocketConfig = defaultSocketConfig;
+ }
+
+ public ConnectionConfig getDefaultConnectionConfig() {
+ return this.defaultConnectionConfig;
+ }
+
+ public void setDefaultConnectionConfig(final ConnectionConfig defaultConnectionConfig) {
+ this.defaultConnectionConfig = defaultConnectionConfig;
+ }
+
+ public SocketConfig getSocketConfig(final HttpHost host) {
+ return this.socketConfigMap.get(host);
+ }
+
+ public void setSocketConfig(final HttpHost host, final SocketConfig socketConfig) {
+ this.socketConfigMap.put(host, socketConfig);
+ }
+
+ public ConnectionConfig getConnectionConfig(final HttpHost host) {
+ return this.connectionConfigMap.get(host);
+ }
+
+ public void setConnectionConfig(final HttpHost host, final ConnectionConfig connectionConfig) {
+ this.connectionConfigMap.put(host, connectionConfig);
+ }
+
+ }
+
+ static class InternalConnectionFactory implements ConnFactory<HttpRoute, ManagedHttpClientConnection> {
+
+ private final ConfigData configData;
+ private final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory;
+
+ InternalConnectionFactory(
+ final ConfigData configData,
+ final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory) {
+ super();
+ this.configData = configData != null ? configData : new ConfigData();
+ this.connFactory = connFactory != null ? connFactory :
+ ManagedHttpClientConnectionFactory.INSTANCE;
+ }
+
+ public ManagedHttpClientConnection create(final HttpRoute route) throws IOException {
+ ConnectionConfig config = null;
+ if (route.getProxyHost() != null) {
+ config = this.configData.getConnectionConfig(route.getProxyHost());
+ }
+ if (config == null) {
+ config = this.configData.getConnectionConfig(route.getTargetHost());
+ }
+ if (config == null) {
+ config = this.configData.getDefaultConnectionConfig();
+ }
+ if (config == null) {
+ config = ConnectionConfig.DEFAULT;
+ }
+ return this.connFactory.create(route, config);
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java
new file mode 100644
index 000000000..8c68e5e18
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java
@@ -0,0 +1,279 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.params.ConnRouteParams;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+
+/**
+ * Default implementation of an {@link HttpRoutePlanner}.
+ * This implementation is based on {@link java.net.ProxySelector}.
+ * By default, it will pick up the proxy settings of the JVM, either
+ * from system properties or from the browser running the application.
+ * Additionally, it interprets some
+ * {@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames parameters},
+ * though not the {@link
+ * ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#DEFAULT_PROXY DEFAULT_PROXY}.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#LOCAL_ADDRESS}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames#FORCED_ROUTE}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link SystemDefaultRoutePlanner}
+ */
+@NotThreadSafe // e.g [gs]etProxySelector()
+@Deprecated
+public class ProxySelectorRoutePlanner implements HttpRoutePlanner {
+
+ /** The scheme registry. */
+ protected final SchemeRegistry schemeRegistry; // @ThreadSafe
+
+ /** The proxy selector to use, or <code>null</code> for system default. */
+ protected ProxySelector proxySelector;
+
+ /**
+ * Creates a new proxy selector route planner.
+ *
+ * @param schreg the scheme registry
+ * @param prosel the proxy selector, or
+ * <code>null</code> for the system default
+ */
+ public ProxySelectorRoutePlanner(final SchemeRegistry schreg,
+ final ProxySelector prosel) {
+ Args.notNull(schreg, "SchemeRegistry");
+ schemeRegistry = schreg;
+ proxySelector = prosel;
+ }
+
+ /**
+ * Obtains the proxy selector to use.
+ *
+ * @return the proxy selector, or <code>null</code> for the system default
+ */
+ public ProxySelector getProxySelector() {
+ return this.proxySelector;
+ }
+
+ /**
+ * Sets the proxy selector to use.
+ *
+ * @param prosel the proxy selector, or
+ * <code>null</code> to use the system default
+ */
+ public void setProxySelector(final ProxySelector prosel) {
+ this.proxySelector = prosel;
+ }
+
+ public HttpRoute determineRoute(final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context)
+ throws HttpException {
+
+ Args.notNull(request, "HTTP request");
+
+ // If we have a forced route, we can do without a target.
+ HttpRoute route =
+ ConnRouteParams.getForcedRoute(request.getParams());
+ if (route != null) {
+ return route;
+ }
+
+ // If we get here, there is no forced route.
+ // So we need a target to compute a route.
+
+ Asserts.notNull(target, "Target host");
+
+ final InetAddress local =
+ ConnRouteParams.getLocalAddress(request.getParams());
+ final HttpHost proxy = determineProxy(target, request, context);
+
+ final Scheme schm =
+ this.schemeRegistry.getScheme(target.getSchemeName());
+ // as it is typically used for TLS/SSL, we assume that
+ // a layered scheme implies a secure connection
+ final boolean secure = schm.isLayered();
+
+ if (proxy == null) {
+ route = new HttpRoute(target, local, secure);
+ } else {
+ route = new HttpRoute(target, local, proxy, secure);
+ }
+ return route;
+ }
+
+ /**
+ * Determines a proxy for the given target.
+ *
+ * @param target the planned target, never <code>null</code>
+ * @param request the request to be sent, never <code>null</code>
+ * @param context the context, or <code>null</code>
+ *
+ * @return the proxy to use, or <code>null</code> for a direct route
+ *
+ * @throws HttpException
+ * in case of system proxy settings that cannot be handled
+ */
+ protected HttpHost determineProxy(final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context)
+ throws HttpException {
+
+ // the proxy selector can be 'unset', so we better deal with null here
+ ProxySelector psel = this.proxySelector;
+ if (psel == null) {
+ psel = ProxySelector.getDefault();
+ }
+ if (psel == null) {
+ return null;
+ }
+
+ URI targetURI = null;
+ try {
+ targetURI = new URI(target.toURI());
+ } catch (final URISyntaxException usx) {
+ throw new HttpException
+ ("Cannot convert host to URI: " + target, usx);
+ }
+ final List<Proxy> proxies = psel.select(targetURI);
+
+ final Proxy p = chooseProxy(proxies, target, request, context);
+
+ HttpHost result = null;
+ if (p.type() == Proxy.Type.HTTP) {
+ // convert the socket address to an HttpHost
+ if (!(p.address() instanceof InetSocketAddress)) {
+ throw new HttpException
+ ("Unable to handle non-Inet proxy address: "+p.address());
+ }
+ final InetSocketAddress isa = (InetSocketAddress) p.address();
+ // assume default scheme (http)
+ result = new HttpHost(getHost(isa), isa.getPort());
+ }
+
+ return result;
+ }
+
+ /**
+ * Obtains a host from an {@link InetSocketAddress}.
+ *
+ * @param isa the socket address
+ *
+ * @return a host string, either as a symbolic name or
+ * as a literal IP address string
+ * <br/>
+ * (TODO: determine format for IPv6 addresses, with or without [brackets])
+ */
+ protected String getHost(final InetSocketAddress isa) {
+
+ //@@@ Will this work with literal IPv6 addresses, or do we
+ //@@@ need to wrap these in [] for the string representation?
+ //@@@ Having it in this method at least allows for easy workarounds.
+ return isa.isUnresolved() ?
+ isa.getHostName() : isa.getAddress().getHostAddress();
+
+ }
+
+ /**
+ * Chooses a proxy from a list of available proxies.
+ * The default implementation just picks the first non-SOCKS proxy
+ * from the list. If there are only SOCKS proxies,
+ * {@link Proxy#NO_PROXY Proxy.NO_PROXY} is returned.
+ * Derived classes may implement more advanced strategies,
+ * such as proxy rotation if there are multiple options.
+ *
+ * @param proxies the list of proxies to choose from,
+ * never <code>null</code> or empty
+ * @param target the planned target, never <code>null</code>
+ * @param request the request to be sent, never <code>null</code>
+ * @param context the context, or <code>null</code>
+ *
+ * @return a proxy type
+ */
+ protected Proxy chooseProxy(final List<Proxy> proxies,
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) {
+ Args.notEmpty(proxies, "List of proxies");
+
+ Proxy result = null;
+
+ // check the list for one we can use
+ for (int i=0; (result == null) && (i < proxies.size()); i++) {
+
+ final Proxy p = proxies.get(i);
+ switch (p.type()) {
+
+ case DIRECT:
+ case HTTP:
+ result = p;
+ break;
+
+ case SOCKS:
+ // SOCKS hosts are not handled on the route level.
+ // The socket may make use of the SOCKS host though.
+ break;
+ }
+ }
+
+ if (result == null) {
+ //@@@ log as warning or info that only a socks proxy is available?
+ // result can only be null if all proxies are socks proxies
+ // socks proxies are not handled on the route planning level
+ result = Proxy.NO_PROXY;
+ }
+
+ return result;
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SchemeRegistryFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SchemeRegistryFactory.java
new file mode 100644
index 000000000..0a17993d1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SchemeRegistryFactory.java
@@ -0,0 +1,90 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.scheme.PlainSocketFactory;
+import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory;
+
+/**
+ * @since 4.1
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.impl.client.HttpClientBuilder}.
+ */
+@ThreadSafe
+@Deprecated
+public final class SchemeRegistryFactory {
+
+ /**
+ * Initializes default scheme registry based on JSSE defaults. System properties will
+ * not be taken into consideration.
+ */
+ public static SchemeRegistry createDefault() {
+ final SchemeRegistry registry = new SchemeRegistry();
+ registry.register(
+ new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
+ registry.register(
+ new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
+ return registry;
+ }
+
+ /**
+ * Initializes default scheme registry using system properties as described in
+ * <a href="http://download.oracle.com/javase/1,5.0/docs/guide/security/jsse/JSSERefGuide.html">
+ * "JavaTM Secure Socket Extension (JSSE) Reference Guide for the JavaTM 2 Platform
+ * Standard Edition 5</a>
+ * <p>
+ * The following system properties are taken into account by this method:
+ * <ul>
+ * <li>ssl.TrustManagerFactory.algorithm</li>
+ * <li>javax.net.ssl.trustStoreType</li>
+ * <li>javax.net.ssl.trustStore</li>
+ * <li>javax.net.ssl.trustStoreProvider</li>
+ * <li>javax.net.ssl.trustStorePassword</li>
+ * <li>java.home</li>
+ * <li>ssl.KeyManagerFactory.algorithm</li>
+ * <li>javax.net.ssl.keyStoreType</li>
+ * <li>javax.net.ssl.keyStore</li>
+ * <li>javax.net.ssl.keyStoreProvider</li>
+ * <li>javax.net.ssl.keyStorePassword</li>
+ * </ul>
+ * <p>
+ *
+ * @since 4.2
+ */
+ public static SchemeRegistry createSystemDefault() {
+ final SchemeRegistry registry = new SchemeRegistry();
+ registry.register(
+ new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
+ registry.register(
+ new Scheme("https", 443, SSLSocketFactory.getSystemSocketFactory()));
+ return registry;
+ }
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SingleClientConnManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SingleClientConnManager.java
new file mode 100644
index 000000000..c2b6c8799
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SingleClientConnManager.java
@@ -0,0 +1,427 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.RouteTracker;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * A connection manager for a single connection. This connection manager
+ * maintains only one active connection at a time. Even though this class
+ * is thread-safe it ought to be used by one execution thread only.
+ * <p>
+ * SingleClientConnManager will make an effort to reuse the connection
+ * for subsequent requests with the same {@link HttpRoute route}.
+ * It will, however, close the existing connection and open it
+ * for the given route, if the route of the persistent connection does
+ * not match that of the connection request. If the connection has been
+ * already been allocated {@link IllegalStateException} is thrown.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link BasicClientConnectionManager}
+ */
+@ThreadSafe
+@Deprecated
+public class SingleClientConnManager implements ClientConnectionManager {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /** The message to be logged on multiple allocation. */
+ public final static String MISUSE_MESSAGE =
+ "Invalid use of SingleClientConnManager: connection still allocated.\n" +
+ "Make sure to release the connection before allocating another one.";
+
+ /** The schemes supported by this connection manager. */
+ protected final SchemeRegistry schemeRegistry;
+
+ /** The operator for opening and updating connections. */
+ protected final ClientConnectionOperator connOperator;
+
+ /** Whether the connection should be shut down on release. */
+ protected final boolean alwaysShutDown;
+
+ /** The one and only entry in this pool. */
+ @GuardedBy("this")
+ protected volatile PoolEntry uniquePoolEntry;
+
+ /** The currently issued managed connection, if any. */
+ @GuardedBy("this")
+ protected volatile ConnAdapter managedConn;
+
+ /** The time of the last connection release, or -1. */
+ @GuardedBy("this")
+ protected volatile long lastReleaseTime;
+
+ /** The time the last released connection expires and shouldn't be reused. */
+ @GuardedBy("this")
+ protected volatile long connectionExpiresTime;
+
+ /** Indicates whether this connection manager is shut down. */
+ protected volatile boolean isShutDown;
+
+ /**
+ * Creates a new simple connection manager.
+ *
+ * @param params the parameters for this manager
+ * @param schreg the scheme registry
+ *
+ * @deprecated (4.1) use {@link SingleClientConnManager#SingleClientConnManager(SchemeRegistry)}
+ */
+ @Deprecated
+ public SingleClientConnManager(final HttpParams params,
+ final SchemeRegistry schreg) {
+ this(schreg);
+ }
+ /**
+ * Creates a new simple connection manager.
+ *
+ * @param schreg the scheme registry
+ */
+ public SingleClientConnManager(final SchemeRegistry schreg) {
+ Args.notNull(schreg, "Scheme registry");
+ this.schemeRegistry = schreg;
+ this.connOperator = createConnectionOperator(schreg);
+ this.uniquePoolEntry = new PoolEntry();
+ this.managedConn = null;
+ this.lastReleaseTime = -1L;
+ this.alwaysShutDown = false; //@@@ from params? as argument?
+ this.isShutDown = false;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public SingleClientConnManager() {
+ this(SchemeRegistryFactory.createDefault());
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally { // Make sure we call overridden method even if shutdown barfs
+ super.finalize();
+ }
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ return this.schemeRegistry;
+ }
+
+ /**
+ * Hook for creating the connection operator.
+ * It is called by the constructor.
+ * Derived classes can override this method to change the
+ * instantiation of the operator.
+ * The default implementation here instantiates
+ * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
+ *
+ * @param schreg the scheme registry to use, or <code>null</code>
+ *
+ * @return the connection operator to use
+ */
+ protected ClientConnectionOperator
+ createConnectionOperator(final SchemeRegistry schreg) {
+ return new DefaultClientConnectionOperator(schreg);
+ }
+
+ /**
+ * Asserts that this manager is not shut down.
+ *
+ * @throws IllegalStateException if this manager is shut down
+ */
+ protected final void assertStillUp() throws IllegalStateException {
+ Asserts.check(!this.isShutDown, "Manager is shut down");
+ }
+
+ public final ClientConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+
+ return new ClientConnectionRequest() {
+
+ public void abortRequest() {
+ // Nothing to abort, since requests are immediate.
+ }
+
+ public ManagedClientConnection getConnection(
+ final long timeout, final TimeUnit tunit) {
+ return SingleClientConnManager.this.getConnection(
+ route, state);
+ }
+
+ };
+ }
+
+ /**
+ * Obtains a connection.
+ *
+ * @param route where the connection should point to
+ *
+ * @return a connection that can be used to communicate
+ * along the given route
+ */
+ public ManagedClientConnection getConnection(final HttpRoute route, final Object state) {
+ Args.notNull(route, "Route");
+ assertStillUp();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Get connection for route " + route);
+ }
+
+ synchronized (this) {
+
+ Asserts.check(managedConn == null, MISUSE_MESSAGE);
+
+ // check re-usability of the connection
+ boolean recreate = false;
+ boolean shutdown = false;
+
+ // Kill the connection if it expired.
+ closeExpiredConnections();
+
+ if (uniquePoolEntry.connection.isOpen()) {
+ final RouteTracker tracker = uniquePoolEntry.tracker;
+ shutdown = (tracker == null || // can happen if method is aborted
+ !tracker.toRoute().equals(route));
+ } else {
+ // If the connection is not open, create a new PoolEntry,
+ // as the connection may have been marked not reusable,
+ // due to aborts -- and the PoolEntry should not be reused
+ // either. There's no harm in recreating an entry if
+ // the connection is closed.
+ recreate = true;
+ }
+
+ if (shutdown) {
+ recreate = true;
+ try {
+ uniquePoolEntry.shutdown();
+ } catch (final IOException iox) {
+ log.debug("Problem shutting down connection.", iox);
+ }
+ }
+
+ if (recreate) {
+ uniquePoolEntry = new PoolEntry();
+ }
+
+ managedConn = new ConnAdapter(uniquePoolEntry, route);
+
+ return managedConn;
+ }
+ }
+
+ public void releaseConnection(
+ final ManagedClientConnection conn,
+ final long validDuration, final TimeUnit timeUnit) {
+ Args.check(conn instanceof ConnAdapter, "Connection class mismatch, " +
+ "connection not obtained from this manager");
+ assertStillUp();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Releasing connection " + conn);
+ }
+
+ final ConnAdapter sca = (ConnAdapter) conn;
+ synchronized (sca) {
+ if (sca.poolEntry == null)
+ {
+ return; // already released
+ }
+ final ClientConnectionManager manager = sca.getManager();
+ Asserts.check(manager == this, "Connection not obtained from this manager");
+ try {
+ // make sure that the response has been read completely
+ if (sca.isOpen() && (this.alwaysShutDown ||
+ !sca.isMarkedReusable())
+ ) {
+ if (log.isDebugEnabled()) {
+ log.debug
+ ("Released connection open but not reusable.");
+ }
+
+ // make sure this connection will not be re-used
+ // we might have gotten here because of a shutdown trigger
+ // shutdown of the adapter also clears the tracked route
+ sca.shutdown();
+ }
+ } catch (final IOException iox) {
+ if (log.isDebugEnabled()) {
+ log.debug("Exception shutting down released connection.",
+ iox);
+ }
+ } finally {
+ sca.detach();
+ synchronized (this) {
+ managedConn = null;
+ lastReleaseTime = System.currentTimeMillis();
+ if(validDuration > 0) {
+ connectionExpiresTime = timeUnit.toMillis(validDuration) + lastReleaseTime;
+ } else {
+ connectionExpiresTime = Long.MAX_VALUE;
+ }
+ }
+ }
+ }
+ }
+
+ public void closeExpiredConnections() {
+ final long time = connectionExpiresTime;
+ if (System.currentTimeMillis() >= time) {
+ closeIdleConnections(0, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
+ assertStillUp();
+
+ // idletime can be 0 or negative, no problem there
+ Args.notNull(tunit, "Time unit");
+
+ synchronized (this) {
+ if ((managedConn == null) && uniquePoolEntry.connection.isOpen()) {
+ final long cutoff =
+ System.currentTimeMillis() - tunit.toMillis(idletime);
+ if (lastReleaseTime <= cutoff) {
+ try {
+ uniquePoolEntry.close();
+ } catch (final IOException iox) {
+ // ignore
+ log.debug("Problem closing idle connection.", iox);
+ }
+ }
+ }
+ }
+ }
+
+ public void shutdown() {
+ this.isShutDown = true;
+ synchronized (this) {
+ try {
+ if (uniquePoolEntry != null) {
+ uniquePoolEntry.shutdown();
+ }
+ } catch (final IOException iox) {
+ // ignore
+ log.debug("Problem while shutting down manager.", iox);
+ } finally {
+ uniquePoolEntry = null;
+ managedConn = null;
+ }
+ }
+ }
+
+ protected void revokeConnection() {
+ final ConnAdapter conn = managedConn;
+ if (conn == null) {
+ return;
+ }
+ conn.detach();
+
+ synchronized (this) {
+ try {
+ uniquePoolEntry.shutdown();
+ } catch (final IOException iox) {
+ // ignore
+ log.debug("Problem while shutting down connection.", iox);
+ }
+ }
+ }
+
+ /**
+ * The pool entry for this connection manager.
+ */
+ protected class PoolEntry extends AbstractPoolEntry {
+
+ /**
+ * Creates a new pool entry.
+ *
+ */
+ protected PoolEntry() {
+ super(SingleClientConnManager.this.connOperator, null);
+ }
+
+ /**
+ * Closes the connection in this pool entry.
+ */
+ protected void close() throws IOException {
+ shutdownEntry();
+ if (connection.isOpen()) {
+ connection.close();
+ }
+ }
+
+ /**
+ * Shuts down the connection in this pool entry.
+ */
+ protected void shutdown() throws IOException {
+ shutdownEntry();
+ if (connection.isOpen()) {
+ connection.shutdown();
+ }
+ }
+
+ }
+
+ /**
+ * The connection adapter used by this manager.
+ */
+ protected class ConnAdapter extends AbstractPooledConnAdapter {
+
+ /**
+ * Creates a new connection adapter.
+ *
+ * @param entry the pool entry for the connection being wrapped
+ * @param route the planned route for this connection
+ */
+ protected ConnAdapter(final PoolEntry entry, final HttpRoute route) {
+ super(SingleClientConnManager.this, entry);
+ markReusable();
+ entry.route = route;
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultDnsResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultDnsResolver.java
new file mode 100644
index 000000000..bb6b7c60d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultDnsResolver.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import ch.boye.httpclientandroidlib.conn.DnsResolver;
+
+/**
+ * DNS resolver that uses the default OS implementation for resolving host names.
+ *
+ * @since 4.2
+ */
+public class SystemDefaultDnsResolver implements DnsResolver {
+
+ public static final SystemDefaultDnsResolver INSTANCE = new SystemDefaultDnsResolver();
+
+ public InetAddress[] resolve(final String host) throws UnknownHostException {
+ return InetAddress.getAllByName(host);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultRoutePlanner.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultRoutePlanner.java
new file mode 100644
index 000000000..27ea2a3d0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/SystemDefaultRoutePlanner.java
@@ -0,0 +1,132 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.conn.SchemePortResolver;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner} implementation
+ * based on {@link ProxySelector}. By default, this class will pick up
+ * the proxy settings of the JVM, either from system properties
+ * or from the browser running the application.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class SystemDefaultRoutePlanner extends DefaultRoutePlanner {
+
+ private final ProxySelector proxySelector;
+
+ public SystemDefaultRoutePlanner(
+ final SchemePortResolver schemePortResolver,
+ final ProxySelector proxySelector) {
+ super(schemePortResolver);
+ this.proxySelector = proxySelector != null ? proxySelector : ProxySelector.getDefault();
+ }
+
+ public SystemDefaultRoutePlanner(final ProxySelector proxySelector) {
+ this(null, proxySelector);
+ }
+
+ @Override
+ protected HttpHost determineProxy(
+ final HttpHost target,
+ final HttpRequest request,
+ final HttpContext context) throws HttpException {
+ final URI targetURI;
+ try {
+ targetURI = new URI(target.toURI());
+ } catch (final URISyntaxException ex) {
+ throw new HttpException("Cannot convert host to URI: " + target, ex);
+ }
+ final List<Proxy> proxies = this.proxySelector.select(targetURI);
+ final Proxy p = chooseProxy(proxies);
+ HttpHost result = null;
+ if (p.type() == Proxy.Type.HTTP) {
+ // convert the socket address to an HttpHost
+ if (!(p.address() instanceof InetSocketAddress)) {
+ throw new HttpException("Unable to handle non-Inet proxy address: " + p.address());
+ }
+ final InetSocketAddress isa = (InetSocketAddress) p.address();
+ // assume default scheme (http)
+ result = new HttpHost(getHost(isa), isa.getPort());
+ }
+
+ return result;
+ }
+
+ private String getHost(final InetSocketAddress isa) {
+
+ //@@@ Will this work with literal IPv6 addresses, or do we
+ //@@@ need to wrap these in [] for the string representation?
+ //@@@ Having it in this method at least allows for easy workarounds.
+ return isa.isUnresolved() ?
+ isa.getHostName() : isa.getAddress().getHostAddress();
+
+ }
+
+ private Proxy chooseProxy(final List<Proxy> proxies) {
+ Proxy result = null;
+ // check the list for one we can use
+ for (int i=0; (result == null) && (i < proxies.size()); i++) {
+ final Proxy p = proxies.get(i);
+ switch (p.type()) {
+
+ case DIRECT:
+ case HTTP:
+ result = p;
+ break;
+
+ case SOCKS:
+ // SOCKS hosts are not handled on the route level.
+ // The socket may make use of the SOCKS host though.
+ break;
+ }
+ }
+ if (result == null) {
+ //@@@ log as warning or info that only a socks proxy is available?
+ // result can only be null if all proxies are socks proxies
+ // socks proxies are not handled on the route planning level
+ result = Proxy.NO_PROXY;
+ }
+ return result;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/Wire.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/Wire.java
new file mode 100644
index 000000000..1a678f05d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/Wire.java
@@ -0,0 +1,152 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Logs data to the wire LOG.
+ * TODO: make package private. Should not be part of the public API.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class Wire {
+
+ public HttpClientAndroidLog log;
+ private final String id;
+
+ /**
+ * @since 4.3
+ */
+ public Wire(final HttpClientAndroidLog log, final String id) {
+ this.log = log;
+ this.id = id;
+ }
+
+ public Wire(final HttpClientAndroidLog log) {
+ this(log, "");
+ }
+
+ private void wire(final String header, final InputStream instream)
+ throws IOException {
+ final StringBuilder buffer = new StringBuilder();
+ int ch;
+ while ((ch = instream.read()) != -1) {
+ if (ch == 13) {
+ buffer.append("[\\r]");
+ } else if (ch == 10) {
+ buffer.append("[\\n]\"");
+ buffer.insert(0, "\"");
+ buffer.insert(0, header);
+ log.debug(id + " " + buffer.toString());
+ buffer.setLength(0);
+ } else if ((ch < 32) || (ch > 127)) {
+ buffer.append("[0x");
+ buffer.append(Integer.toHexString(ch));
+ buffer.append("]");
+ } else {
+ buffer.append((char) ch);
+ }
+ }
+ if (buffer.length() > 0) {
+ buffer.append('\"');
+ buffer.insert(0, '\"');
+ buffer.insert(0, header);
+ log.debug(id + " " + buffer.toString());
+ }
+ }
+
+
+ public boolean enabled() {
+ return log.isDebugEnabled();
+ }
+
+ public void output(final InputStream outstream)
+ throws IOException {
+ Args.notNull(outstream, "Output");
+ wire(">> ", outstream);
+ }
+
+ public void input(final InputStream instream)
+ throws IOException {
+ Args.notNull(instream, "Input");
+ wire("<< ", instream);
+ }
+
+ public void output(final byte[] b, final int off, final int len)
+ throws IOException {
+ Args.notNull(b, "Output");
+ wire(">> ", new ByteArrayInputStream(b, off, len));
+ }
+
+ public void input(final byte[] b, final int off, final int len)
+ throws IOException {
+ Args.notNull(b, "Input");
+ wire("<< ", new ByteArrayInputStream(b, off, len));
+ }
+
+ public void output(final byte[] b)
+ throws IOException {
+ Args.notNull(b, "Output");
+ wire(">> ", new ByteArrayInputStream(b));
+ }
+
+ public void input(final byte[] b)
+ throws IOException {
+ Args.notNull(b, "Input");
+ wire("<< ", new ByteArrayInputStream(b));
+ }
+
+ public void output(final int b)
+ throws IOException {
+ output(new byte[] {(byte) b});
+ }
+
+ public void input(final int b)
+ throws IOException {
+ input(new byte[] {(byte) b});
+ }
+
+ public void output(final String s)
+ throws IOException {
+ Args.notNull(s, "Output");
+ output(s.getBytes());
+ }
+
+ public void input(final String s)
+ throws IOException {
+ Args.notNull(s, "Input");
+ input(s.getBytes());
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/package-info.java
new file mode 100644
index 000000000..49305e4b7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default implementations of client connection management
+ * functions.
+ */
+package ch.boye.httpclientandroidlib.impl.conn;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java
new file mode 100644
index 000000000..f85539c2d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java
@@ -0,0 +1,234 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.impl.conn.IdleConnectionHandler;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * An abstract connection pool.
+ * It is used by the {@link ThreadSafeClientConnManager}.
+ * The abstract pool includes a {@link #poolLock}, which is used to
+ * synchronize access to the internal pool datastructures.
+ * Don't use <code>synchronized</code> for that purpose!
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.AbstractConnPool}
+ */
+@Deprecated
+public abstract class AbstractConnPool {
+
+ public HttpClientAndroidLog log;
+
+ /**
+ * The global lock for this pool.
+ */
+ protected final Lock poolLock;
+
+ /** References to issued connections */
+ @GuardedBy("poolLock")
+ protected Set<BasicPoolEntry> leasedConnections;
+
+ /** The current total number of connections. */
+ @GuardedBy("poolLock")
+ protected int numConnections;
+
+ /** Indicates whether this pool is shut down. */
+ protected volatile boolean isShutDown;
+
+ protected Set<BasicPoolEntryRef> issuedConnections;
+
+ protected ReferenceQueue<Object> refQueue;
+
+ protected IdleConnectionHandler idleConnHandler;
+
+ /**
+ * Creates a new connection pool.
+ */
+ protected AbstractConnPool() {
+ super();
+ this.log = new HttpClientAndroidLog(getClass());
+ this.leasedConnections = new HashSet<BasicPoolEntry>();
+ this.idleConnHandler = new IdleConnectionHandler();
+ this.poolLock = new ReentrantLock();
+ }
+
+ public void enableConnectionGC()
+ throws IllegalStateException {
+ }
+
+ /**
+ * Obtains a pool entry with a connection within the given timeout.
+ *
+ * @param route the route for which to get the connection
+ * @param timeout the timeout, 0 or negative for no timeout
+ * @param tunit the unit for the <code>timeout</code>,
+ * may be <code>null</code> only if there is no timeout
+ *
+ * @return pool entry holding a connection for the route
+ *
+ * @throws ConnectionPoolTimeoutException
+ * if the timeout expired
+ * @throws InterruptedException
+ * if the calling thread was interrupted
+ */
+ public final
+ BasicPoolEntry getEntry(
+ final HttpRoute route,
+ final Object state,
+ final long timeout,
+ final TimeUnit tunit)
+ throws ConnectionPoolTimeoutException, InterruptedException {
+ return requestPoolEntry(route, state).getPoolEntry(timeout, tunit);
+ }
+
+ /**
+ * Returns a new {@link PoolEntryRequest}, from which a {@link BasicPoolEntry}
+ * can be obtained, or the request can be aborted.
+ */
+ public abstract PoolEntryRequest requestPoolEntry(HttpRoute route, Object state);
+
+
+ /**
+ * Returns an entry into the pool.
+ * The connection of the entry is expected to be in a suitable state,
+ * either open and re-usable, or closed. The pool will not make any
+ * attempt to determine whether it can be re-used or not.
+ *
+ * @param entry the entry for the connection to release
+ * @param reusable <code>true</code> if the entry is deemed
+ * reusable, <code>false</code> otherwise.
+ * @param validDuration The duration that the entry should remain free and reusable.
+ * @param timeUnit The unit of time the duration is measured in.
+ */
+ public abstract void freeEntry(BasicPoolEntry entry, boolean reusable, long validDuration, TimeUnit timeUnit)
+ ;
+
+ public void handleReference(final Reference<?> ref) {
+ }
+
+ protected abstract void handleLostEntry(HttpRoute route);
+
+ /**
+ * Closes idle connections.
+ *
+ * @param idletime the time the connections should have been idle
+ * in order to be closed now
+ * @param tunit the unit for the <code>idletime</code>
+ */
+ public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
+
+ // idletime can be 0 or negative, no problem there
+ Args.notNull(tunit, "Time unit");
+
+ poolLock.lock();
+ try {
+ idleConnHandler.closeIdleConnections(tunit.toMillis(idletime));
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ public void closeExpiredConnections() {
+ poolLock.lock();
+ try {
+ idleConnHandler.closeExpiredConnections();
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+
+ /**
+ * Deletes all entries for closed connections.
+ */
+ public abstract void deleteClosedConnections();
+
+ /**
+ * Shuts down this pool and all associated resources.
+ * Overriding methods MUST call the implementation here!
+ */
+ public void shutdown() {
+
+ poolLock.lock();
+ try {
+
+ if (isShutDown) {
+ return;
+ }
+
+ // close all connections that are issued to an application
+ final Iterator<BasicPoolEntry> iter = leasedConnections.iterator();
+ while (iter.hasNext()) {
+ final BasicPoolEntry entry = iter.next();
+ iter.remove();
+ closeConnection(entry.getConnection());
+ }
+ idleConnHandler.removeAll();
+
+ isShutDown = true;
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+
+ /**
+ * Closes a connection from this pool.
+ *
+ * @param conn the connection to close, or <code>null</code>
+ */
+ protected void closeConnection(final OperatedClientConnection conn) {
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (final IOException ex) {
+ log.debug("I/O error closing connection", ex);
+ }
+ }
+ }
+
+} // class AbstractConnPool
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java
new file mode 100644
index 000000000..2c5bf05ce
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java
@@ -0,0 +1,163 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import java.lang.ref.ReferenceQueue;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.impl.conn.AbstractPoolEntry;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of a connection pool entry.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.PoolEntry}
+ */
+@Deprecated
+public class BasicPoolEntry extends AbstractPoolEntry {
+
+ private final long created;
+
+ private long updated;
+ private final long validUntil;
+ private long expiry;
+
+ public BasicPoolEntry(final ClientConnectionOperator op,
+ final HttpRoute route,
+ final ReferenceQueue<Object> queue) {
+ super(op, route);
+ Args.notNull(route, "HTTP route");
+ this.created = System.currentTimeMillis();
+ this.validUntil = Long.MAX_VALUE;
+ this.expiry = this.validUntil;
+ }
+
+ /**
+ * Creates a new pool entry.
+ *
+ * @param op the connection operator
+ * @param route the planned route for the connection
+ */
+ public BasicPoolEntry(final ClientConnectionOperator op,
+ final HttpRoute route) {
+ this(op, route, -1, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Creates a new pool entry with a specified maximum lifetime.
+ *
+ * @param op the connection operator
+ * @param route the planned route for the connection
+ * @param connTTL maximum lifetime of this entry, <=0 implies "infinity"
+ * @param timeunit TimeUnit of connTTL
+ *
+ * @since 4.1
+ */
+ public BasicPoolEntry(final ClientConnectionOperator op,
+ final HttpRoute route, final long connTTL, final TimeUnit timeunit) {
+ super(op, route);
+ Args.notNull(route, "HTTP route");
+ this.created = System.currentTimeMillis();
+ if (connTTL > 0) {
+ this.validUntil = this.created + timeunit.toMillis(connTTL);
+ } else {
+ this.validUntil = Long.MAX_VALUE;
+ }
+ this.expiry = this.validUntil;
+ }
+
+ protected final OperatedClientConnection getConnection() {
+ return super.connection;
+ }
+
+ protected final HttpRoute getPlannedRoute() {
+ return super.route;
+ }
+
+ protected final BasicPoolEntryRef getWeakRef() {
+ return null;
+ }
+
+ @Override
+ protected void shutdownEntry() {
+ super.shutdownEntry();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public long getCreated() {
+ return this.created;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public long getUpdated() {
+ return this.updated;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public long getExpiry() {
+ return this.expiry;
+ }
+
+ public long getValidUntil() {
+ return this.validUntil;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public void updateExpiry(final long time, final TimeUnit timeunit) {
+ this.updated = System.currentTimeMillis();
+ final long newExpiry;
+ if (time > 0) {
+ newExpiry = this.updated + timeunit.toMillis(time);
+ } else {
+ newExpiry = Long.MAX_VALUE;
+ }
+ this.expiry = Math.min(validUntil, newExpiry);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public boolean isExpired(final long now) {
+ return now >= this.expiry;
+ }
+
+}
+
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java
new file mode 100644
index 000000000..202e6b102
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java
@@ -0,0 +1,76 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A weak reference to a {@link BasicPoolEntry BasicPoolEntry}.
+ * This reference explicitly keeps the planned route, so the connection
+ * can be reclaimed if it is lost to garbage collection.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+public class BasicPoolEntryRef extends WeakReference<BasicPoolEntry> {
+
+ /** The planned route of the entry. */
+ private final HttpRoute route; // HttpRoute is @Immutable
+
+
+ /**
+ * Creates a new reference to a pool entry.
+ *
+ * @param entry the pool entry, must not be <code>null</code>
+ * @param queue the reference queue, or <code>null</code>
+ */
+ public BasicPoolEntryRef(final BasicPoolEntry entry,
+ final ReferenceQueue<Object> queue) {
+ super(entry, queue);
+ Args.notNull(entry, "Pool entry");
+ route = entry.getPlannedRoute();
+ }
+
+
+ /**
+ * Obtain the planned route for the referenced entry.
+ * The planned route is still available, even if the entry is gone.
+ *
+ * @return the planned route
+ */
+ public final HttpRoute getRoute() {
+ return this.route;
+ }
+
+} // class BasicPoolEntryRef
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java
new file mode 100644
index 000000000..3d6433a2d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.impl.conn.AbstractPoolEntry;
+import ch.boye.httpclientandroidlib.impl.conn.AbstractPooledConnAdapter;
+
+/**
+ * A connection wrapper and callback handler.
+ * All connections given out by the manager are wrappers which
+ * can be {@link #detach detach}ed to prevent further use on release.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+public class BasicPooledConnAdapter extends AbstractPooledConnAdapter {
+
+ /**
+ * Creates a new adapter.
+ *
+ * @param tsccm the connection manager
+ * @param entry the pool entry for the connection being wrapped
+ */
+ protected BasicPooledConnAdapter(final ThreadSafeClientConnManager tsccm,
+ final AbstractPoolEntry entry) {
+ super(tsccm, entry);
+ markReusable();
+ }
+
+ @Override
+ protected ClientConnectionManager getManager() {
+ // override needed only to make method visible in this package
+ return super.getManager();
+ }
+
+ @Override
+ protected AbstractPoolEntry getPoolEntry() {
+ // override needed only to make method visible in this package
+ return super.getPoolEntry();
+ }
+
+ @Override
+ protected void detach() {
+ // override needed only to make method visible in this package
+ super.detach();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java
new file mode 100644
index 000000000..22f6a089d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java
@@ -0,0 +1,829 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.params.ConnManagerParams;
+import ch.boye.httpclientandroidlib.conn.params.ConnPerRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * A connection pool that maintains connections by route.
+ * This class is derived from <code>MultiThreadedHttpConnectionManager</code>
+ * in HttpClient 3.x, see there for original authors. It implements the same
+ * algorithm for connection re-use and connection-per-host enforcement:
+ * <ul>
+ * <li>connections are re-used only for the exact same route</li>
+ * <li>connection limits are enforced per route rather than per host</li>
+ * </ul>
+ * Note that access to the pool data structures is synchronized via the
+ * {@link AbstractConnPool#poolLock poolLock} in the base class,
+ * not via <code>synchronized</code> methods.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.AbstractConnPool}
+ */
+@Deprecated
+public class ConnPoolByRoute extends AbstractConnPool {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final Lock poolLock;
+
+ /** Connection operator for this pool */
+ protected final ClientConnectionOperator operator;
+
+ /** Connections per route lookup */
+ protected final ConnPerRoute connPerRoute;
+
+ /** References to issued connections */
+ protected final Set<BasicPoolEntry> leasedConnections;
+
+ /** The list of free connections */
+ protected final Queue<BasicPoolEntry> freeConnections;
+
+ /** The list of WaitingThreads waiting for a connection */
+ protected final Queue<WaitingThread> waitingThreads;
+
+ /** Map of route-specific pools */
+ protected final Map<HttpRoute, RouteSpecificPool> routeToPool;
+
+ private final long connTTL;
+
+ private final TimeUnit connTTLTimeUnit;
+
+ protected volatile boolean shutdown;
+
+ protected volatile int maxTotalConnections;
+
+ protected volatile int numConnections;
+
+ /**
+ * Creates a new connection pool, managed by route.
+ *
+ * @since 4.1
+ */
+ public ConnPoolByRoute(
+ final ClientConnectionOperator operator,
+ final ConnPerRoute connPerRoute,
+ final int maxTotalConnections) {
+ this(operator, connPerRoute, maxTotalConnections, -1, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public ConnPoolByRoute(
+ final ClientConnectionOperator operator,
+ final ConnPerRoute connPerRoute,
+ final int maxTotalConnections,
+ final long connTTL,
+ final TimeUnit connTTLTimeUnit) {
+ super();
+ Args.notNull(operator, "Connection operator");
+ Args.notNull(connPerRoute, "Connections per route");
+ this.poolLock = super.poolLock;
+ this.leasedConnections = super.leasedConnections;
+ this.operator = operator;
+ this.connPerRoute = connPerRoute;
+ this.maxTotalConnections = maxTotalConnections;
+ this.freeConnections = createFreeConnQueue();
+ this.waitingThreads = createWaitingThreadQueue();
+ this.routeToPool = createRouteToPoolMap();
+ this.connTTL = connTTL;
+ this.connTTLTimeUnit = connTTLTimeUnit;
+ }
+
+ protected Lock getLock() {
+ return this.poolLock;
+ }
+
+ /**
+ * Creates a new connection pool, managed by route.
+ *
+ * @deprecated (4.1) use {@link ConnPoolByRoute#ConnPoolByRoute(ClientConnectionOperator, ConnPerRoute, int)}
+ */
+ @Deprecated
+ public ConnPoolByRoute(final ClientConnectionOperator operator, final HttpParams params) {
+ this(operator,
+ ConnManagerParams.getMaxConnectionsPerRoute(params),
+ ConnManagerParams.getMaxTotalConnections(params));
+ }
+
+ /**
+ * Creates the queue for {@link #freeConnections}.
+ * Called once by the constructor.
+ *
+ * @return a queue
+ */
+ protected Queue<BasicPoolEntry> createFreeConnQueue() {
+ return new LinkedList<BasicPoolEntry>();
+ }
+
+ /**
+ * Creates the queue for {@link #waitingThreads}.
+ * Called once by the constructor.
+ *
+ * @return a queue
+ */
+ protected Queue<WaitingThread> createWaitingThreadQueue() {
+ return new LinkedList<WaitingThread>();
+ }
+
+ /**
+ * Creates the map for {@link #routeToPool}.
+ * Called once by the constructor.
+ *
+ * @return a map
+ */
+ protected Map<HttpRoute, RouteSpecificPool> createRouteToPoolMap() {
+ return new HashMap<HttpRoute, RouteSpecificPool>();
+ }
+
+
+ /**
+ * Creates a new route-specific pool.
+ * Called by {@link #getRoutePool} when necessary.
+ *
+ * @param route the route
+ *
+ * @return the new pool
+ */
+ protected RouteSpecificPool newRouteSpecificPool(final HttpRoute route) {
+ return new RouteSpecificPool(route, this.connPerRoute);
+ }
+
+
+ /**
+ * Creates a new waiting thread.
+ * Called by {@link #getRoutePool} when necessary.
+ *
+ * @param cond the condition to wait for
+ * @param rospl the route specific pool, or <code>null</code>
+ *
+ * @return a waiting thread representation
+ */
+ protected WaitingThread newWaitingThread(final Condition cond,
+ final RouteSpecificPool rospl) {
+ return new WaitingThread(cond, rospl);
+ }
+
+ private void closeConnection(final BasicPoolEntry entry) {
+ final OperatedClientConnection conn = entry.getConnection();
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (final IOException ex) {
+ log.debug("I/O error closing connection", ex);
+ }
+ }
+ }
+
+ /**
+ * Get a route-specific pool of available connections.
+ *
+ * @param route the route
+ * @param create whether to create the pool if it doesn't exist
+ *
+ * @return the pool for the argument route,
+ * never <code>null</code> if <code>create</code> is <code>true</code>
+ */
+ protected RouteSpecificPool getRoutePool(final HttpRoute route,
+ final boolean create) {
+ RouteSpecificPool rospl = null;
+ poolLock.lock();
+ try {
+
+ rospl = routeToPool.get(route);
+ if ((rospl == null) && create) {
+ // no pool for this route yet (or anymore)
+ rospl = newRouteSpecificPool(route);
+ routeToPool.put(route, rospl);
+ }
+
+ } finally {
+ poolLock.unlock();
+ }
+
+ return rospl;
+ }
+
+ public int getConnectionsInPool(final HttpRoute route) {
+ poolLock.lock();
+ try {
+ // don't allow a pool to be created here!
+ final RouteSpecificPool rospl = getRoutePool(route, false);
+ return (rospl != null) ? rospl.getEntryCount() : 0;
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ public int getConnectionsInPool() {
+ poolLock.lock();
+ try {
+ return numConnections;
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ @Override
+ public PoolEntryRequest requestPoolEntry(
+ final HttpRoute route,
+ final Object state) {
+
+ final WaitingThreadAborter aborter = new WaitingThreadAborter();
+
+ return new PoolEntryRequest() {
+
+ public void abortRequest() {
+ poolLock.lock();
+ try {
+ aborter.abort();
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ public BasicPoolEntry getPoolEntry(
+ final long timeout,
+ final TimeUnit tunit)
+ throws InterruptedException, ConnectionPoolTimeoutException {
+ return getEntryBlocking(route, state, timeout, tunit, aborter);
+ }
+
+ };
+ }
+
+ /**
+ * Obtains a pool entry with a connection within the given timeout.
+ * If a {@link WaitingThread} is used to block, {@link WaitingThreadAborter#setWaitingThread(WaitingThread)}
+ * must be called before blocking, to allow the thread to be interrupted.
+ *
+ * @param route the route for which to get the connection
+ * @param timeout the timeout, 0 or negative for no timeout
+ * @param tunit the unit for the <code>timeout</code>,
+ * may be <code>null</code> only if there is no timeout
+ * @param aborter an object which can abort a {@link WaitingThread}.
+ *
+ * @return pool entry holding a connection for the route
+ *
+ * @throws ConnectionPoolTimeoutException
+ * if the timeout expired
+ * @throws InterruptedException
+ * if the calling thread was interrupted
+ */
+ protected BasicPoolEntry getEntryBlocking(
+ final HttpRoute route, final Object state,
+ final long timeout, final TimeUnit tunit,
+ final WaitingThreadAborter aborter)
+ throws ConnectionPoolTimeoutException, InterruptedException {
+
+ Date deadline = null;
+ if (timeout > 0) {
+ deadline = new Date
+ (System.currentTimeMillis() + tunit.toMillis(timeout));
+ }
+
+ BasicPoolEntry entry = null;
+ poolLock.lock();
+ try {
+
+ RouteSpecificPool rospl = getRoutePool(route, true);
+ WaitingThread waitingThread = null;
+
+ while (entry == null) {
+ Asserts.check(!shutdown, "Connection pool shut down");
+
+ if (log.isDebugEnabled()) {
+ log.debug("[" + route + "] total kept alive: " + freeConnections.size() +
+ ", total issued: " + leasedConnections.size() +
+ ", total allocated: " + numConnections + " out of " + maxTotalConnections);
+ }
+
+ // the cases to check for:
+ // - have a free connection for that route
+ // - allowed to create a free connection for that route
+ // - can delete and replace a free connection for another route
+ // - need to wait for one of the things above to come true
+
+ entry = getFreeEntry(rospl, state);
+ if (entry != null) {
+ break;
+ }
+
+ final boolean hasCapacity = rospl.getCapacity() > 0;
+
+ if (log.isDebugEnabled()) {
+ log.debug("Available capacity: " + rospl.getCapacity()
+ + " out of " + rospl.getMaxEntries()
+ + " [" + route + "][" + state + "]");
+ }
+
+ if (hasCapacity && numConnections < maxTotalConnections) {
+
+ entry = createEntry(rospl, operator);
+
+ } else if (hasCapacity && !freeConnections.isEmpty()) {
+
+ deleteLeastUsedEntry();
+ // if least used entry's route was the same as rospl,
+ // rospl is now out of date : we preemptively refresh
+ rospl = getRoutePool(route, true);
+ entry = createEntry(rospl, operator);
+
+ } else {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Need to wait for connection" +
+ " [" + route + "][" + state + "]");
+ }
+
+ if (waitingThread == null) {
+ waitingThread =
+ newWaitingThread(poolLock.newCondition(), rospl);
+ aborter.setWaitingThread(waitingThread);
+ }
+
+ boolean success = false;
+ try {
+ rospl.queueThread(waitingThread);
+ waitingThreads.add(waitingThread);
+ success = waitingThread.await(deadline);
+
+ } finally {
+ // In case of 'success', we were woken up by the
+ // connection pool and should now have a connection
+ // waiting for us, or else we're shutting down.
+ // Just continue in the loop, both cases are checked.
+ rospl.removeThread(waitingThread);
+ waitingThreads.remove(waitingThread);
+ }
+
+ // check for spurious wakeup vs. timeout
+ if (!success && (deadline != null) &&
+ (deadline.getTime() <= System.currentTimeMillis())) {
+ throw new ConnectionPoolTimeoutException
+ ("Timeout waiting for connection from pool");
+ }
+ }
+ } // while no entry
+
+ } finally {
+ poolLock.unlock();
+ }
+ return entry;
+ }
+
+ @Override
+ public void freeEntry(final BasicPoolEntry entry, final boolean reusable, final long validDuration, final TimeUnit timeUnit) {
+
+ final HttpRoute route = entry.getPlannedRoute();
+ if (log.isDebugEnabled()) {
+ log.debug("Releasing connection" +
+ " [" + route + "][" + entry.getState() + "]");
+ }
+
+ poolLock.lock();
+ try {
+ if (shutdown) {
+ // the pool is shut down, release the
+ // connection's resources and get out of here
+ closeConnection(entry);
+ return;
+ }
+
+ // no longer issued, we keep a hard reference now
+ leasedConnections.remove(entry);
+
+ final RouteSpecificPool rospl = getRoutePool(route, true);
+
+ if (reusable && rospl.getCapacity() >= 0) {
+ if (log.isDebugEnabled()) {
+ final String s;
+ if (validDuration > 0) {
+ s = "for " + validDuration + " " + timeUnit;
+ } else {
+ s = "indefinitely";
+ }
+ log.debug("Pooling connection" +
+ " [" + route + "][" + entry.getState() + "]; keep alive " + s);
+ }
+ rospl.freeEntry(entry);
+ entry.updateExpiry(validDuration, timeUnit);
+ freeConnections.add(entry);
+ } else {
+ closeConnection(entry);
+ rospl.dropEntry();
+ numConnections--;
+ }
+
+ notifyWaitingThread(rospl);
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ /**
+ * If available, get a free pool entry for a route.
+ *
+ * @param rospl the route-specific pool from which to get an entry
+ *
+ * @return an available pool entry for the given route, or
+ * <code>null</code> if none is available
+ */
+ protected BasicPoolEntry getFreeEntry(final RouteSpecificPool rospl, final Object state) {
+
+ BasicPoolEntry entry = null;
+ poolLock.lock();
+ try {
+ boolean done = false;
+ while(!done) {
+
+ entry = rospl.allocEntry(state);
+
+ if (entry != null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Getting free connection"
+ + " [" + rospl.getRoute() + "][" + state + "]");
+
+ }
+ freeConnections.remove(entry);
+ if (entry.isExpired(System.currentTimeMillis())) {
+ // If the free entry isn't valid anymore, get rid of it
+ // and loop to find another one that might be valid.
+ if (log.isDebugEnabled()) {
+ log.debug("Closing expired free connection"
+ + " [" + rospl.getRoute() + "][" + state + "]");
+ }
+ closeConnection(entry);
+ // We use dropEntry instead of deleteEntry because the entry
+ // is no longer "free" (we just allocated it), and deleteEntry
+ // can only be used to delete free entries.
+ rospl.dropEntry();
+ numConnections--;
+ } else {
+ leasedConnections.add(entry);
+ done = true;
+ }
+
+ } else {
+ done = true;
+ if (log.isDebugEnabled()) {
+ log.debug("No free connections"
+ + " [" + rospl.getRoute() + "][" + state + "]");
+ }
+ }
+ }
+ } finally {
+ poolLock.unlock();
+ }
+ return entry;
+ }
+
+
+ /**
+ * Creates a new pool entry.
+ * This method assumes that the new connection will be handed
+ * out immediately.
+ *
+ * @param rospl the route-specific pool for which to create the entry
+ * @param op the operator for creating a connection
+ *
+ * @return the new pool entry for a new connection
+ */
+ protected BasicPoolEntry createEntry(final RouteSpecificPool rospl,
+ final ClientConnectionOperator op) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Creating new connection [" + rospl.getRoute() + "]");
+ }
+
+ // the entry will create the connection when needed
+ final BasicPoolEntry entry = new BasicPoolEntry(op, rospl.getRoute(), connTTL, connTTLTimeUnit);
+
+ poolLock.lock();
+ try {
+ rospl.createdEntry(entry);
+ numConnections++;
+ leasedConnections.add(entry);
+ } finally {
+ poolLock.unlock();
+ }
+
+ return entry;
+ }
+
+
+ /**
+ * Deletes a given pool entry.
+ * This closes the pooled connection and removes all references,
+ * so that it can be GCed.
+ *
+ * <p><b>Note:</b> Does not remove the entry from the freeConnections list.
+ * It is assumed that the caller has already handled this step.</p>
+ * <!-- @@@ is that a good idea? or rather fix it? -->
+ *
+ * @param entry the pool entry for the connection to delete
+ */
+ protected void deleteEntry(final BasicPoolEntry entry) {
+
+ final HttpRoute route = entry.getPlannedRoute();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Deleting connection"
+ + " [" + route + "][" + entry.getState() + "]");
+ }
+
+ poolLock.lock();
+ try {
+
+ closeConnection(entry);
+
+ final RouteSpecificPool rospl = getRoutePool(route, true);
+ rospl.deleteEntry(entry);
+ numConnections--;
+ if (rospl.isUnused()) {
+ routeToPool.remove(route);
+ }
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+
+ /**
+ * Delete an old, free pool entry to make room for a new one.
+ * Used to replace pool entries with ones for a different route.
+ */
+ protected void deleteLeastUsedEntry() {
+ poolLock.lock();
+ try {
+
+ final BasicPoolEntry entry = freeConnections.remove();
+
+ if (entry != null) {
+ deleteEntry(entry);
+ } else if (log.isDebugEnabled()) {
+ log.debug("No free connection to delete");
+ }
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ @Override
+ protected void handleLostEntry(final HttpRoute route) {
+
+ poolLock.lock();
+ try {
+
+ final RouteSpecificPool rospl = getRoutePool(route, true);
+ rospl.dropEntry();
+ if (rospl.isUnused()) {
+ routeToPool.remove(route);
+ }
+
+ numConnections--;
+ notifyWaitingThread(rospl);
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ /**
+ * Notifies a waiting thread that a connection is available.
+ * This will wake a thread waiting in the specific route pool,
+ * if there is one.
+ * Otherwise, a thread in the connection pool will be notified.
+ *
+ * @param rospl the pool in which to notify, or <code>null</code>
+ */
+ protected void notifyWaitingThread(final RouteSpecificPool rospl) {
+
+ //@@@ while this strategy provides for best connection re-use,
+ //@@@ is it fair? only do this if the connection is open?
+ // Find the thread we are going to notify. We want to ensure that
+ // each waiting thread is only interrupted once, so we will remove
+ // it from all wait queues before interrupting.
+ WaitingThread waitingThread = null;
+
+ poolLock.lock();
+ try {
+
+ if ((rospl != null) && rospl.hasThread()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Notifying thread waiting on pool" +
+ " [" + rospl.getRoute() + "]");
+ }
+ waitingThread = rospl.nextThread();
+ } else if (!waitingThreads.isEmpty()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Notifying thread waiting on any pool");
+ }
+ waitingThread = waitingThreads.remove();
+ } else if (log.isDebugEnabled()) {
+ log.debug("Notifying no-one, there are no waiting threads");
+ }
+
+ if (waitingThread != null) {
+ waitingThread.wakeup();
+ }
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+
+ @Override
+ public void deleteClosedConnections() {
+ poolLock.lock();
+ try {
+ final Iterator<BasicPoolEntry> iter = freeConnections.iterator();
+ while (iter.hasNext()) {
+ final BasicPoolEntry entry = iter.next();
+ if (!entry.getConnection().isOpen()) {
+ iter.remove();
+ deleteEntry(entry);
+ }
+ }
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ /**
+ * Closes idle connections.
+ *
+ * @param idletime the time the connections should have been idle
+ * in order to be closed now
+ * @param tunit the unit for the <code>idletime</code>
+ */
+ @Override
+ public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
+ Args.notNull(tunit, "Time unit");
+ final long t = idletime > 0 ? idletime : 0;
+ if (log.isDebugEnabled()) {
+ log.debug("Closing connections idle longer than " + t + " " + tunit);
+ }
+ // the latest time for which connections will be closed
+ final long deadline = System.currentTimeMillis() - tunit.toMillis(t);
+ poolLock.lock();
+ try {
+ final Iterator<BasicPoolEntry> iter = freeConnections.iterator();
+ while (iter.hasNext()) {
+ final BasicPoolEntry entry = iter.next();
+ if (entry.getUpdated() <= deadline) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing connection last used @ " + new Date(entry.getUpdated()));
+ }
+ iter.remove();
+ deleteEntry(entry);
+ }
+ }
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ @Override
+ public void closeExpiredConnections() {
+ log.debug("Closing expired connections");
+ final long now = System.currentTimeMillis();
+
+ poolLock.lock();
+ try {
+ final Iterator<BasicPoolEntry> iter = freeConnections.iterator();
+ while (iter.hasNext()) {
+ final BasicPoolEntry entry = iter.next();
+ if (entry.isExpired(now)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing connection expired @ " + new Date(entry.getExpiry()));
+ }
+ iter.remove();
+ deleteEntry(entry);
+ }
+ }
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ poolLock.lock();
+ try {
+ if (shutdown) {
+ return;
+ }
+ shutdown = true;
+
+ // close all connections that are issued to an application
+ final Iterator<BasicPoolEntry> iter1 = leasedConnections.iterator();
+ while (iter1.hasNext()) {
+ final BasicPoolEntry entry = iter1.next();
+ iter1.remove();
+ closeConnection(entry);
+ }
+
+ // close all free connections
+ final Iterator<BasicPoolEntry> iter2 = freeConnections.iterator();
+ while (iter2.hasNext()) {
+ final BasicPoolEntry entry = iter2.next();
+ iter2.remove();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Closing connection"
+ + " [" + entry.getPlannedRoute() + "][" + entry.getState() + "]");
+ }
+ closeConnection(entry);
+ }
+
+ // wake up all waiting threads
+ final Iterator<WaitingThread> iwth = waitingThreads.iterator();
+ while (iwth.hasNext()) {
+ final WaitingThread waiter = iwth.next();
+ iwth.remove();
+ waiter.wakeup();
+ }
+
+ routeToPool.clear();
+
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+ /**
+ * since 4.1
+ */
+ public void setMaxTotalConnections(final int max) {
+ poolLock.lock();
+ try {
+ maxTotalConnections = max;
+ } finally {
+ poolLock.unlock();
+ }
+ }
+
+
+ /**
+ * since 4.1
+ */
+ public int getMaxTotalConnections() {
+ return maxTotalConnections;
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java
new file mode 100644
index 000000000..bf7eb147f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
+
+/**
+ * Encapsulates a request for a {@link BasicPoolEntry}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link java.util.concurrent.Future}
+ */
+@Deprecated
+public interface PoolEntryRequest {
+
+ /**
+ * Obtains a pool entry with a connection within the given timeout.
+ * If {@link #abortRequest()} is called before this completes
+ * an {@link InterruptedException} is thrown.
+ *
+ * @param timeout the timeout, 0 or negative for no timeout
+ * @param tunit the unit for the <code>timeout</code>,
+ * may be <code>null</code> only if there is no timeout
+ *
+ * @return pool entry holding a connection for the route
+ *
+ * @throws ConnectionPoolTimeoutException
+ * if the timeout expired
+ * @throws InterruptedException
+ * if the calling thread was interrupted or the request was aborted
+ */
+ BasicPoolEntry getPoolEntry(
+ long timeout,
+ TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException;
+
+ /**
+ * Aborts the active or next call to
+ * {@link #getPoolEntry(long, TimeUnit)}.
+ */
+ void abortRequest();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java
new file mode 100644
index 000000000..73964c8d1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java
@@ -0,0 +1,313 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Queue;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
+import ch.boye.httpclientandroidlib.conn.params.ConnPerRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+
+/**
+ * A connection sub-pool for a specific route, used by {@link ConnPoolByRoute}.
+ * The methods in this class are unsynchronized. It is expected that the
+ * containing pool takes care of synchronization.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.AbstractConnPool}
+ */
+@Deprecated
+public class RouteSpecificPool {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ /** The route this pool is for. */
+ protected final HttpRoute route; //Immutable
+
+ protected final int maxEntries;
+
+ /** Connections per route */
+ protected final ConnPerRoute connPerRoute;
+
+ /**
+ * The list of free entries.
+ * This list is managed LIFO, to increase idle times and
+ * allow for closing connections that are not really needed.
+ */
+ protected final LinkedList<BasicPoolEntry> freeEntries;
+
+ /** The list of threads waiting for this pool. */
+ protected final Queue<WaitingThread> waitingThreads;
+
+ /** The number of created entries. */
+ protected int numEntries;
+
+ /**
+ * @deprecated (4.1) use {@link RouteSpecificPool#RouteSpecificPool(HttpRoute, ConnPerRoute)}
+ */
+ @Deprecated
+ public RouteSpecificPool(final HttpRoute route, final int maxEntries) {
+ this.route = route;
+ this.maxEntries = maxEntries;
+ this.connPerRoute = new ConnPerRoute() {
+ public int getMaxForRoute(final HttpRoute route) {
+ return RouteSpecificPool.this.maxEntries;
+ }
+ };
+ this.freeEntries = new LinkedList<BasicPoolEntry>();
+ this.waitingThreads = new LinkedList<WaitingThread>();
+ this.numEntries = 0;
+ }
+
+
+ /**
+ * Creates a new route-specific pool.
+ *
+ * @param route the route for which to pool
+ * @param connPerRoute the connections per route configuration
+ */
+ public RouteSpecificPool(final HttpRoute route, final ConnPerRoute connPerRoute) {
+ this.route = route;
+ this.connPerRoute = connPerRoute;
+ this.maxEntries = connPerRoute.getMaxForRoute(route);
+ this.freeEntries = new LinkedList<BasicPoolEntry>();
+ this.waitingThreads = new LinkedList<WaitingThread>();
+ this.numEntries = 0;
+ }
+
+
+ /**
+ * Obtains the route for which this pool is specific.
+ *
+ * @return the route
+ */
+ public final HttpRoute getRoute() {
+ return route;
+ }
+
+
+ /**
+ * Obtains the maximum number of entries allowed for this pool.
+ *
+ * @return the max entry number
+ */
+ public final int getMaxEntries() {
+ return maxEntries;
+ }
+
+
+ /**
+ * Indicates whether this pool is unused.
+ * A pool is unused if there is neither an entry nor a waiting thread.
+ * All entries count, not only the free but also the allocated ones.
+ *
+ * @return <code>true</code> if this pool is unused,
+ * <code>false</code> otherwise
+ */
+ public boolean isUnused() {
+ return (numEntries < 1) && waitingThreads.isEmpty();
+ }
+
+
+ /**
+ * Return remaining capacity of this pool
+ *
+ * @return capacity
+ */
+ public int getCapacity() {
+ return connPerRoute.getMaxForRoute(route) - numEntries;
+ }
+
+
+ /**
+ * Obtains the number of entries.
+ * This includes not only the free entries, but also those that
+ * have been created and are currently issued to an application.
+ *
+ * @return the number of entries for the route of this pool
+ */
+ public final int getEntryCount() {
+ return numEntries;
+ }
+
+
+ /**
+ * Obtains a free entry from this pool, if one is available.
+ *
+ * @return an available pool entry, or <code>null</code> if there is none
+ */
+ public BasicPoolEntry allocEntry(final Object state) {
+ if (!freeEntries.isEmpty()) {
+ final ListIterator<BasicPoolEntry> it = freeEntries.listIterator(freeEntries.size());
+ while (it.hasPrevious()) {
+ final BasicPoolEntry entry = it.previous();
+ if (entry.getState() == null || LangUtils.equals(state, entry.getState())) {
+ it.remove();
+ return entry;
+ }
+ }
+ }
+ if (getCapacity() == 0 && !freeEntries.isEmpty()) {
+ final BasicPoolEntry entry = freeEntries.remove();
+ entry.shutdownEntry();
+ final OperatedClientConnection conn = entry.getConnection();
+ try {
+ conn.close();
+ } catch (final IOException ex) {
+ log.debug("I/O error closing connection", ex);
+ }
+ return entry;
+ }
+ return null;
+ }
+
+
+ /**
+ * Returns an allocated entry to this pool.
+ *
+ * @param entry the entry obtained from {@link #allocEntry allocEntry}
+ * or presented to {@link #createdEntry createdEntry}
+ */
+ public void freeEntry(final BasicPoolEntry entry) {
+ if (numEntries < 1) {
+ throw new IllegalStateException
+ ("No entry created for this pool. " + route);
+ }
+ if (numEntries <= freeEntries.size()) {
+ throw new IllegalStateException
+ ("No entry allocated from this pool. " + route);
+ }
+ freeEntries.add(entry);
+ }
+
+
+ /**
+ * Indicates creation of an entry for this pool.
+ * The entry will <i>not</i> be added to the list of free entries,
+ * it is only recognized as belonging to this pool now. It can then
+ * be passed to {@link #freeEntry freeEntry}.
+ *
+ * @param entry the entry that was created for this pool
+ */
+ public void createdEntry(final BasicPoolEntry entry) {
+ Args.check(route.equals(entry.getPlannedRoute()), "Entry not planned for this pool");
+ numEntries++;
+ }
+
+
+ /**
+ * Deletes an entry from this pool.
+ * Only entries that are currently free in this pool can be deleted.
+ * Allocated entries can not be deleted.
+ *
+ * @param entry the entry to delete from this pool
+ *
+ * @return <code>true</code> if the entry was found and deleted, or
+ * <code>false</code> if the entry was not found
+ */
+ public boolean deleteEntry(final BasicPoolEntry entry) {
+
+ final boolean found = freeEntries.remove(entry);
+ if (found) {
+ numEntries--;
+ }
+ return found;
+ }
+
+
+ /**
+ * Forgets about an entry from this pool.
+ * This method is used to indicate that an entry
+ * {@link #allocEntry allocated}
+ * from this pool has been lost and will not be returned.
+ */
+ public void dropEntry() {
+ Asserts.check(numEntries > 0, "There is no entry that could be dropped");
+ numEntries--;
+ }
+
+
+ /**
+ * Adds a waiting thread.
+ * This pool makes no attempt to match waiting threads with pool entries.
+ * It is the caller's responsibility to check that there is no entry
+ * before adding a waiting thread.
+ *
+ * @param wt the waiting thread
+ */
+ public void queueThread(final WaitingThread wt) {
+ Args.notNull(wt, "Waiting thread");
+ this.waitingThreads.add(wt);
+ }
+
+
+ /**
+ * Checks whether there is a waiting thread in this pool.
+ *
+ * @return <code>true</code> if there is a waiting thread,
+ * <code>false</code> otherwise
+ */
+ public boolean hasThread() {
+ return !this.waitingThreads.isEmpty();
+ }
+
+
+ /**
+ * Returns the next thread in the queue.
+ *
+ * @return a waiting thread, or <code>null</code> if there is none
+ */
+ public WaitingThread nextThread() {
+ return this.waitingThreads.peek();
+ }
+
+
+ /**
+ * Removes a waiting thread, if it is queued.
+ *
+ * @param wt the waiting thread
+ */
+ public void removeThread(final WaitingThread wt) {
+ if (wt == null) {
+ return;
+ }
+
+ this.waitingThreads.remove(wt);
+ }
+
+
+} // class RouteSpecificPool
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java
new file mode 100644
index 000000000..1a1ff5c37
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java
@@ -0,0 +1,377 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
+import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
+import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
+import ch.boye.httpclientandroidlib.conn.params.ConnPerRouteBean;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
+import ch.boye.httpclientandroidlib.impl.conn.DefaultClientConnectionOperator;
+import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Manages a pool of {@link ch.boye.httpclientandroidlib.conn.OperatedClientConnection }
+ * and is able to service connection requests from multiple execution threads.
+ * Connections are pooled on a per route basis. A request for a route which
+ * already the manager has persistent connections for available in the pool
+ * will be services by leasing a connection from the pool rather than
+ * creating a brand new connection.
+ * <p>
+ * ThreadSafeClientConnManager maintains a maximum limit of connection on
+ * a per route basis and in total. Per default this implementation will
+ * create no more than than 2 concurrent connections per given route
+ * and no more 20 connections in total. For many real-world applications
+ * these limits may prove too constraining, especially if they use HTTP
+ * as a transport protocol for their services. Connection limits, however,
+ * can be adjusted using HTTP parameters.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.impl.conn.PoolingHttpClientConnectionManager}
+ */
+@ThreadSafe
+@Deprecated
+public class ThreadSafeClientConnManager implements ClientConnectionManager {
+
+ public HttpClientAndroidLog log;
+
+ /** The schemes supported by this connection manager. */
+ protected final SchemeRegistry schemeRegistry; // @ThreadSafe
+
+ protected final AbstractConnPool connectionPool;
+
+ /** The pool of connections being managed. */
+ protected final ConnPoolByRoute pool;
+
+ /** The operator for opening and updating connections. */
+ protected final ClientConnectionOperator connOperator; // DefaultClientConnectionOperator is @ThreadSafe
+
+ protected final ConnPerRouteBean connPerRoute;
+
+ /**
+ * Creates a new thread safe connection manager.
+ *
+ * @param schreg the scheme registry.
+ */
+ public ThreadSafeClientConnManager(final SchemeRegistry schreg) {
+ this(schreg, -1, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public ThreadSafeClientConnManager() {
+ this(SchemeRegistryFactory.createDefault());
+ }
+
+ /**
+ * Creates a new thread safe connection manager.
+ *
+ * @param schreg the scheme registry.
+ * @param connTTL max connection lifetime, <=0 implies "infinity"
+ * @param connTTLTimeUnit TimeUnit of connTTL
+ *
+ * @since 4.1
+ */
+ public ThreadSafeClientConnManager(final SchemeRegistry schreg,
+ final long connTTL, final TimeUnit connTTLTimeUnit) {
+ this(schreg, connTTL, connTTLTimeUnit, new ConnPerRouteBean());
+ }
+
+ /**
+ * Creates a new thread safe connection manager.
+ *
+ * @param schreg the scheme registry.
+ * @param connTTL max connection lifetime, <=0 implies "infinity"
+ * @param connTTLTimeUnit TimeUnit of connTTL
+ * @param connPerRoute mapping of maximum connections per route,
+ * provided as a dependency so it can be managed externally, e.g.
+ * for dynamic connection pool size management.
+ *
+ * @since 4.2
+ */
+ public ThreadSafeClientConnManager(final SchemeRegistry schreg,
+ final long connTTL, final TimeUnit connTTLTimeUnit, final ConnPerRouteBean connPerRoute) {
+ super();
+ Args.notNull(schreg, "Scheme registry");
+ this.log = new HttpClientAndroidLog(getClass());
+ this.schemeRegistry = schreg;
+ this.connPerRoute = connPerRoute;
+ this.connOperator = createConnectionOperator(schreg);
+ this.pool = createConnectionPool(connTTL, connTTLTimeUnit) ;
+ this.connectionPool = this.pool;
+ }
+
+ /**
+ * Creates a new thread safe connection manager.
+ *
+ * @param params the parameters for this manager.
+ * @param schreg the scheme registry.
+ *
+ * @deprecated (4.1) use {@link ThreadSafeClientConnManager#ThreadSafeClientConnManager(SchemeRegistry)}
+ */
+ @Deprecated
+ public ThreadSafeClientConnManager(final HttpParams params,
+ final SchemeRegistry schreg) {
+ Args.notNull(schreg, "Scheme registry");
+ this.log = new HttpClientAndroidLog(getClass());
+ this.schemeRegistry = schreg;
+ this.connPerRoute = new ConnPerRouteBean();
+ this.connOperator = createConnectionOperator(schreg);
+ this.pool = (ConnPoolByRoute) createConnectionPool(params) ;
+ this.connectionPool = this.pool;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Hook for creating the connection pool.
+ *
+ * @return the connection pool to use
+ *
+ * @deprecated (4.1) use #createConnectionPool(long, TimeUnit))
+ */
+ @Deprecated
+ protected AbstractConnPool createConnectionPool(final HttpParams params) {
+ return new ConnPoolByRoute(connOperator, params);
+ }
+
+ /**
+ * Hook for creating the connection pool.
+ *
+ * @return the connection pool to use
+ *
+ * @since 4.1
+ */
+ protected ConnPoolByRoute createConnectionPool(final long connTTL, final TimeUnit connTTLTimeUnit) {
+ return new ConnPoolByRoute(connOperator, connPerRoute, 20, connTTL, connTTLTimeUnit);
+ }
+
+ /**
+ * Hook for creating the connection operator.
+ * It is called by the constructor.
+ * Derived classes can override this method to change the
+ * instantiation of the operator.
+ * The default implementation here instantiates
+ * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
+ *
+ * @param schreg the scheme registry.
+ *
+ * @return the connection operator to use
+ */
+ protected ClientConnectionOperator
+ createConnectionOperator(final SchemeRegistry schreg) {
+
+ return new DefaultClientConnectionOperator(schreg);// @ThreadSafe
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ return this.schemeRegistry;
+ }
+
+ public ClientConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+
+ final PoolEntryRequest poolRequest = pool.requestPoolEntry(
+ route, state);
+
+ return new ClientConnectionRequest() {
+
+ public void abortRequest() {
+ poolRequest.abortRequest();
+ }
+
+ public ManagedClientConnection getConnection(
+ final long timeout, final TimeUnit tunit) throws InterruptedException,
+ ConnectionPoolTimeoutException {
+ Args.notNull(route, "Route");
+
+ if (log.isDebugEnabled()) {
+ log.debug("Get connection: " + route + ", timeout = " + timeout);
+ }
+
+ final BasicPoolEntry entry = poolRequest.getPoolEntry(timeout, tunit);
+ return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry);
+ }
+
+ };
+
+ }
+
+ public void releaseConnection(final ManagedClientConnection conn, final long validDuration, final TimeUnit timeUnit) {
+ Args.check(conn instanceof BasicPooledConnAdapter, "Connection class mismatch, " +
+ "connection not obtained from this manager");
+ final BasicPooledConnAdapter hca = (BasicPooledConnAdapter) conn;
+ if (hca.getPoolEntry() != null) {
+ Asserts.check(hca.getManager() == this, "Connection not obtained from this manager");
+ }
+ synchronized (hca) {
+ final BasicPoolEntry entry = (BasicPoolEntry) hca.getPoolEntry();
+ if (entry == null) {
+ return;
+ }
+ try {
+ // make sure that the response has been read completely
+ if (hca.isOpen() && !hca.isMarkedReusable()) {
+ // In MTHCM, there would be a call to
+ // SimpleHttpConnectionManager.finishLastResponse(conn);
+ // Consuming the response is handled outside in 4.0.
+
+ // make sure this connection will not be re-used
+ // Shut down rather than close, we might have gotten here
+ // because of a shutdown trigger.
+ // Shutdown of the adapter also clears the tracked route.
+ hca.shutdown();
+ }
+ } catch (final IOException iox) {
+ if (log.isDebugEnabled()) {
+ log.debug("Exception shutting down released connection.",
+ iox);
+ }
+ } finally {
+ final boolean reusable = hca.isMarkedReusable();
+ if (log.isDebugEnabled()) {
+ if (reusable) {
+ log.debug("Released connection is reusable.");
+ } else {
+ log.debug("Released connection is not reusable.");
+ }
+ }
+ hca.detach();
+ pool.freeEntry(entry, reusable, validDuration, timeUnit);
+ }
+ }
+ }
+
+ public void shutdown() {
+ log.debug("Shutting down");
+ pool.shutdown();
+ }
+
+ /**
+ * Gets the total number of pooled connections for the given route.
+ * This is the total number of connections that have been created and
+ * are still in use by this connection manager for the route.
+ * This value will not exceed the maximum number of connections per host.
+ *
+ * @param route the route in question
+ *
+ * @return the total number of pooled connections for that route
+ */
+ public int getConnectionsInPool(final HttpRoute route) {
+ return pool.getConnectionsInPool(route);
+ }
+
+ /**
+ * Gets the total number of pooled connections. This is the total number of
+ * connections that have been created and are still in use by this connection
+ * manager. This value will not exceed the maximum number of connections
+ * in total.
+ *
+ * @return the total number of pooled connections
+ */
+ public int getConnectionsInPool() {
+ return pool.getConnectionsInPool();
+ }
+
+ public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit);
+ }
+ pool.closeIdleConnections(idleTimeout, tunit);
+ }
+
+ public void closeExpiredConnections() {
+ log.debug("Closing expired connections");
+ pool.closeExpiredConnections();
+ }
+
+ /**
+ * since 4.1
+ */
+ public int getMaxTotal() {
+ return pool.getMaxTotalConnections();
+ }
+
+ /**
+ * since 4.1
+ */
+ public void setMaxTotal(final int max) {
+ pool.setMaxTotalConnections(max);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int getDefaultMaxPerRoute() {
+ return connPerRoute.getDefaultMaxPerRoute();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public void setDefaultMaxPerRoute(final int max) {
+ connPerRoute.setDefaultMaxPerRoute(max);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int getMaxForRoute(final HttpRoute route) {
+ return connPerRoute.getMaxForRoute(route);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public void setMaxForRoute(final HttpRoute route, final int max) {
+ connPerRoute.setMaxForRoute(route, max);
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThread.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThread.java
new file mode 100644
index 000000000..c3f46cacf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThread.java
@@ -0,0 +1,198 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+
+import java.util.Date;
+import java.util.concurrent.locks.Condition;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Represents a thread waiting for a connection.
+ * This class implements throwaway objects. It is instantiated whenever
+ * a thread needs to wait. Instances are not re-used, except if the
+ * waiting thread experiences a spurious wakeup and continues to wait.
+ * <br/>
+ * All methods assume external synchronization on the condition
+ * passed to the constructor.
+ * Instances of this class do <i>not</i> synchronize access!
+ *
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+public class WaitingThread {
+
+ /** The condition on which the thread is waiting. */
+ private final Condition cond;
+
+ /** The route specific pool on which the thread is waiting. */
+ //@@@ replace with generic pool interface
+ private final RouteSpecificPool pool;
+
+ /** The thread that is waiting for an entry. */
+ private Thread waiter;
+
+ /** True if this was interrupted. */
+ private boolean aborted;
+
+
+ /**
+ * Creates a new entry for a waiting thread.
+ *
+ * @param cond the condition for which to wait
+ * @param pool the pool on which the thread will be waiting,
+ * or <code>null</code>
+ */
+ public WaitingThread(final Condition cond, final RouteSpecificPool pool) {
+
+ Args.notNull(cond, "Condition");
+
+ this.cond = cond;
+ this.pool = pool;
+ }
+
+
+ /**
+ * Obtains the condition.
+ *
+ * @return the condition on which to wait, never <code>null</code>
+ */
+ public final Condition getCondition() {
+ // not synchronized
+ return this.cond;
+ }
+
+
+ /**
+ * Obtains the pool, if there is one.
+ *
+ * @return the pool on which a thread is or was waiting,
+ * or <code>null</code>
+ */
+ public final RouteSpecificPool getPool() {
+ // not synchronized
+ return this.pool;
+ }
+
+
+ /**
+ * Obtains the thread, if there is one.
+ *
+ * @return the thread which is waiting, or <code>null</code>
+ */
+ public final Thread getThread() {
+ // not synchronized
+ return this.waiter;
+ }
+
+
+ /**
+ * Blocks the calling thread.
+ * This method returns when the thread is notified or interrupted,
+ * if a timeout occurrs, or if there is a spurious wakeup.
+ * <br/>
+ * This method assumes external synchronization.
+ *
+ * @param deadline when to time out, or <code>null</code> for no timeout
+ *
+ * @return <code>true</code> if the condition was satisfied,
+ * <code>false</code> in case of a timeout.
+ * Typically, a call to {@link #wakeup} is used to indicate
+ * that the condition was satisfied. Since the condition is
+ * accessible outside, this cannot be guaranteed though.
+ *
+ * @throws InterruptedException if the waiting thread was interrupted
+ *
+ * @see #wakeup
+ */
+ public boolean await(final Date deadline)
+ throws InterruptedException {
+
+ // This is only a sanity check. We cannot synchronize here,
+ // the lock would not be released on calling cond.await() below.
+ if (this.waiter != null) {
+ throw new IllegalStateException
+ ("A thread is already waiting on this object." +
+ "\ncaller: " + Thread.currentThread() +
+ "\nwaiter: " + this.waiter);
+ }
+
+ if (aborted) {
+ throw new InterruptedException("Operation interrupted");
+ }
+
+ this.waiter = Thread.currentThread();
+
+ boolean success = false;
+ try {
+ if (deadline != null) {
+ success = this.cond.awaitUntil(deadline);
+ } else {
+ this.cond.await();
+ success = true;
+ }
+ if (aborted) {
+ throw new InterruptedException("Operation interrupted");
+ }
+ } finally {
+ this.waiter = null;
+ }
+ return success;
+
+ } // await
+
+
+ /**
+ * Wakes up the waiting thread.
+ * <br/>
+ * This method assumes external synchronization.
+ */
+ public void wakeup() {
+
+ // If external synchronization and pooling works properly,
+ // this cannot happen. Just a sanity check.
+ if (this.waiter == null) {
+ throw new IllegalStateException
+ ("Nobody waiting on this object.");
+ }
+
+ // One condition might be shared by several WaitingThread instances.
+ // It probably isn't, but just in case: wake all, not just one.
+ this.cond.signalAll();
+ }
+
+ public void interrupt() {
+ aborted = true;
+ this.cond.signalAll();
+ }
+
+
+} // class WaitingThread
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java
new file mode 100644
index 000000000..7ad999996
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
+
+/**
+ * A simple class that can interrupt a {@link WaitingThread}.
+ *
+ * Must be called with the pool lock held.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) do not use
+ */
+@Deprecated
+public class WaitingThreadAborter {
+
+ private WaitingThread waitingThread;
+ private boolean aborted;
+
+ /**
+ * If a waiting thread has been set, interrupts it.
+ */
+ public void abort() {
+ aborted = true;
+
+ if (waitingThread != null) {
+ waitingThread.interrupt();
+ }
+
+ }
+
+ /**
+ * Sets the waiting thread. If this has already been aborted,
+ * the waiting thread is immediately interrupted.
+ *
+ * @param waitingThread The thread to interrupt when aborting.
+ */
+ public void setWaitingThread(final WaitingThread waitingThread) {
+ this.waitingThread = waitingThread;
+ if (aborted) {
+ waitingThread.interrupt();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/package-info.java
new file mode 100644
index 000000000..5115d461f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/package-info.java
@@ -0,0 +1,33 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Deprecated.
+ *
+ * @deprecated (4.3)
+ */
+package ch.boye.httpclientandroidlib.impl.conn.tsccm;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java
new file mode 100644
index 000000000..e9406bab2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java
@@ -0,0 +1,52 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public abstract class AbstractCookieAttributeHandler implements CookieAttributeHandler {
+
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ // Do nothing
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ // Always match
+ return true;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieSpec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieSpec.java
new file mode 100644
index 000000000..7dc320ef4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/AbstractCookieSpec.java
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Abstract cookie specification which can delegate the job of parsing,
+ * validation or matching cookie attributes to a number of arbitrary
+ * {@link CookieAttributeHandler}s.
+ *
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // HashMap is not thread-safe
+public abstract class AbstractCookieSpec implements CookieSpec {
+
+ /**
+ * Stores attribute name -> attribute handler mappings
+ */
+ private final Map<String, CookieAttributeHandler> attribHandlerMap;
+
+ /**
+ * Default constructor
+ * */
+ public AbstractCookieSpec() {
+ super();
+ this.attribHandlerMap = new HashMap<String, CookieAttributeHandler>(10);
+ }
+
+ public void registerAttribHandler(
+ final String name, final CookieAttributeHandler handler) {
+ Args.notNull(name, "Attribute name");
+ Args.notNull(handler, "Attribute handler");
+ this.attribHandlerMap.put(name, handler);
+ }
+
+ /**
+ * Finds an attribute handler {@link CookieAttributeHandler} for the
+ * given attribute. Returns <tt>null</tt> if no attribute handler is
+ * found for the specified attribute.
+ *
+ * @param name attribute name. e.g. Domain, Path, etc.
+ * @return an attribute handler or <tt>null</tt>
+ */
+ protected CookieAttributeHandler findAttribHandler(final String name) {
+ return this.attribHandlerMap.get(name);
+ }
+
+ /**
+ * Gets attribute handler {@link CookieAttributeHandler} for the
+ * given attribute.
+ *
+ * @param name attribute name. e.g. Domain, Path, etc.
+ * @throws IllegalStateException if handler not found for the
+ * specified attribute.
+ */
+ protected CookieAttributeHandler getAttribHandler(final String name) {
+ final CookieAttributeHandler handler = findAttribHandler(name);
+ if (handler == null) {
+ throw new IllegalStateException("Handler not registered for " +
+ name + " attribute.");
+ } else {
+ return handler;
+ }
+ }
+
+ protected Collection<CookieAttributeHandler> getAttribHandlers() {
+ return this.attribHandlerMap.values();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie.java
new file mode 100644
index 000000000..c826daada
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie.java
@@ -0,0 +1,361 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of {@link SetCookie}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicClientCookie implements SetCookie, ClientCookie, Cloneable, Serializable {
+
+ private static final long serialVersionUID = -3869795591041535538L;
+
+ /**
+ * Default Constructor taking a name and a value. The value may be null.
+ *
+ * @param name The name.
+ * @param value The value.
+ */
+ public BasicClientCookie(final String name, final String value) {
+ super();
+ Args.notNull(name, "Name");
+ this.name = name;
+ this.attribs = new HashMap<String, String>();
+ this.value = value;
+ }
+
+ /**
+ * Returns the name.
+ *
+ * @return String name The name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Returns the value.
+ *
+ * @return String value The current value.
+ */
+ public String getValue() {
+ return this.value;
+ }
+
+ /**
+ * Sets the value
+ *
+ * @param value
+ */
+ public void setValue(final String value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns the comment describing the purpose of this cookie, or
+ * <tt>null</tt> if no such comment has been defined.
+ *
+ * @return comment
+ *
+ * @see #setComment(String)
+ */
+ public String getComment() {
+ return cookieComment;
+ }
+
+ /**
+ * If a user agent (web browser) presents this cookie to a user, the
+ * cookie's purpose will be described using this comment.
+ *
+ * @param comment
+ *
+ * @see #getComment()
+ */
+ public void setComment(final String comment) {
+ cookieComment = comment;
+ }
+
+
+ /**
+ * Returns null. Cookies prior to RFC2965 do not set this attribute
+ */
+ public String getCommentURL() {
+ return null;
+ }
+
+
+ /**
+ * Returns the expiration {@link Date} of the cookie, or <tt>null</tt>
+ * if none exists.
+ * <p><strong>Note:</strong> the object returned by this method is
+ * considered immutable. Changing it (e.g. using setTime()) could result
+ * in undefined behaviour. Do so at your peril. </p>
+ * @return Expiration {@link Date}, or <tt>null</tt>.
+ *
+ * @see #setExpiryDate(java.util.Date)
+ *
+ */
+ public Date getExpiryDate() {
+ return cookieExpiryDate;
+ }
+
+ /**
+ * Sets expiration date.
+ * <p><strong>Note:</strong> the object returned by this method is considered
+ * immutable. Changing it (e.g. using setTime()) could result in undefined
+ * behaviour. Do so at your peril.</p>
+ *
+ * @param expiryDate the {@link Date} after which this cookie is no longer valid.
+ *
+ * @see #getExpiryDate
+ *
+ */
+ public void setExpiryDate (final Date expiryDate) {
+ cookieExpiryDate = expiryDate;
+ }
+
+
+ /**
+ * Returns <tt>false</tt> if the cookie should be discarded at the end
+ * of the "session"; <tt>true</tt> otherwise.
+ *
+ * @return <tt>false</tt> if the cookie should be discarded at the end
+ * of the "session"; <tt>true</tt> otherwise
+ */
+ public boolean isPersistent() {
+ return (null != cookieExpiryDate);
+ }
+
+
+ /**
+ * Returns domain attribute of the cookie.
+ *
+ * @return the value of the domain attribute
+ *
+ * @see #setDomain(java.lang.String)
+ */
+ public String getDomain() {
+ return cookieDomain;
+ }
+
+ /**
+ * Sets the domain attribute.
+ *
+ * @param domain The value of the domain attribute
+ *
+ * @see #getDomain
+ */
+ public void setDomain(final String domain) {
+ if (domain != null) {
+ cookieDomain = domain.toLowerCase(Locale.ENGLISH);
+ } else {
+ cookieDomain = null;
+ }
+ }
+
+
+ /**
+ * Returns the path attribute of the cookie
+ *
+ * @return The value of the path attribute.
+ *
+ * @see #setPath(java.lang.String)
+ */
+ public String getPath() {
+ return cookiePath;
+ }
+
+ /**
+ * Sets the path attribute.
+ *
+ * @param path The value of the path attribute
+ *
+ * @see #getPath
+ *
+ */
+ public void setPath(final String path) {
+ cookiePath = path;
+ }
+
+ /**
+ * @return <code>true</code> if this cookie should only be sent over secure connections.
+ * @see #setSecure(boolean)
+ */
+ public boolean isSecure() {
+ return isSecure;
+ }
+
+ /**
+ * Sets the secure attribute of the cookie.
+ * <p>
+ * When <tt>true</tt> the cookie should only be sent
+ * using a secure protocol (https). This should only be set when
+ * the cookie's originating server used a secure protocol to set the
+ * cookie's value.
+ *
+ * @param secure The value of the secure attribute
+ *
+ * @see #isSecure()
+ */
+ public void setSecure (final boolean secure) {
+ isSecure = secure;
+ }
+
+
+ /**
+ * Returns null. Cookies prior to RFC2965 do not set this attribute
+ */
+ public int[] getPorts() {
+ return null;
+ }
+
+
+ /**
+ * Returns the version of the cookie specification to which this
+ * cookie conforms.
+ *
+ * @return the version of the cookie.
+ *
+ * @see #setVersion(int)
+ *
+ */
+ public int getVersion() {
+ return cookieVersion;
+ }
+
+ /**
+ * Sets the version of the cookie specification to which this
+ * cookie conforms.
+ *
+ * @param version the version of the cookie.
+ *
+ * @see #getVersion
+ */
+ public void setVersion(final int version) {
+ cookieVersion = version;
+ }
+
+ /**
+ * Returns true if this cookie has expired.
+ * @param date Current time
+ *
+ * @return <tt>true</tt> if the cookie has expired.
+ */
+ public boolean isExpired(final Date date) {
+ Args.notNull(date, "Date");
+ return (cookieExpiryDate != null
+ && cookieExpiryDate.getTime() <= date.getTime());
+ }
+
+ public void setAttribute(final String name, final String value) {
+ this.attribs.put(name, value);
+ }
+
+ public String getAttribute(final String name) {
+ return this.attribs.get(name);
+ }
+
+ public boolean containsAttribute(final String name) {
+ return this.attribs.get(name) != null;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ final BasicClientCookie clone = (BasicClientCookie) super.clone();
+ clone.attribs = new HashMap<String, String>(this.attribs);
+ return clone;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("[version: ");
+ buffer.append(Integer.toString(this.cookieVersion));
+ buffer.append("]");
+ buffer.append("[name: ");
+ buffer.append(this.name);
+ buffer.append("]");
+ buffer.append("[value: ");
+ buffer.append(this.value);
+ buffer.append("]");
+ buffer.append("[domain: ");
+ buffer.append(this.cookieDomain);
+ buffer.append("]");
+ buffer.append("[path: ");
+ buffer.append(this.cookiePath);
+ buffer.append("]");
+ buffer.append("[expiry: ");
+ buffer.append(this.cookieExpiryDate);
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** Cookie name */
+ private final String name;
+
+ /** Cookie attributes as specified by the origin server */
+ private Map<String, String> attribs;
+
+ /** Cookie value */
+ private String value;
+
+ /** Comment attribute. */
+ private String cookieComment;
+
+ /** Domain attribute. */
+ private String cookieDomain;
+
+ /** Expiration {@link Date}. */
+ private Date cookieExpiryDate;
+
+ /** Path attribute. */
+ private String cookiePath;
+
+ /** My secure flag. */
+ private boolean isSecure;
+
+ /** The version of the cookie specification I was created from. */
+ private int cookieVersion;
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie2.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie2.java
new file mode 100644
index 000000000..7ed0f82b6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicClientCookie2.java
@@ -0,0 +1,101 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Date;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.SetCookie2;
+
+/**
+ * Default implementation of {@link SetCookie2}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicClientCookie2 extends BasicClientCookie implements SetCookie2 {
+
+ private static final long serialVersionUID = -7744598295706617057L;
+
+ private String commentURL;
+ private int[] ports;
+ private boolean discard;
+
+ /**
+ * Default Constructor taking a name and a value. The value may be null.
+ *
+ * @param name The name.
+ * @param value The value.
+ */
+ public BasicClientCookie2(final String name, final String value) {
+ super(name, value);
+ }
+
+ @Override
+ public int[] getPorts() {
+ return this.ports;
+ }
+
+ public void setPorts(final int[] ports) {
+ this.ports = ports;
+ }
+
+ @Override
+ public String getCommentURL() {
+ return this.commentURL;
+ }
+
+ public void setCommentURL(final String commentURL) {
+ this.commentURL = commentURL;
+ }
+
+ public void setDiscard(final boolean discard) {
+ this.discard = discard;
+ }
+
+ @Override
+ public boolean isPersistent() {
+ return !this.discard && super.isPersistent();
+ }
+
+ @Override
+ public boolean isExpired(final Date date) {
+ return this.discard || super.isExpired(date);
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ final BasicClientCookie2 clone = (BasicClientCookie2) super.clone();
+ if (this.ports != null) {
+ clone.ports = this.ports.clone();
+ }
+ return clone;
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicCommentHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicCommentHandler.java
new file mode 100644
index 000000000..69d65b961
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicCommentHandler.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicCommentHandler extends AbstractCookieAttributeHandler {
+
+ public BasicCommentHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ cookie.setComment(value);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicDomainHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicDomainHandler.java
new file mode 100644
index 000000000..bad00ec48
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicDomainHandler.java
@@ -0,0 +1,116 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicDomainHandler implements CookieAttributeHandler {
+
+ public BasicDomainHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (value == null) {
+ throw new MalformedCookieException("Missing value for domain attribute");
+ }
+ if (value.trim().length() == 0) {
+ throw new MalformedCookieException("Blank value for domain attribute");
+ }
+ cookie.setDomain(value);
+ }
+
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ // Validate the cookies domain attribute. NOTE: Domains without
+ // any dots are allowed to support hosts on private LANs that don't
+ // have DNS names. Since they have no dots, to domain-match the
+ // request-host and domain must be identical for the cookie to sent
+ // back to the origin-server.
+ final String host = origin.getHost();
+ String domain = cookie.getDomain();
+ if (domain == null) {
+ throw new CookieRestrictionViolationException("Cookie domain may not be null");
+ }
+ if (host.contains(".")) {
+ // Not required to have at least two dots. RFC 2965.
+ // A Set-Cookie2 with Domain=ajax.com will be accepted.
+
+ // domain must match host
+ if (!host.endsWith(domain)) {
+ if (domain.startsWith(".")) {
+ domain = domain.substring(1, domain.length());
+ }
+ if (!host.equals(domain)) {
+ throw new CookieRestrictionViolationException(
+ "Illegal domain attribute \"" + domain
+ + "\". Domain of origin: \"" + host + "\"");
+ }
+ }
+ } else {
+ if (!host.equals(domain)) {
+ throw new CookieRestrictionViolationException(
+ "Illegal domain attribute \"" + domain
+ + "\". Domain of origin: \"" + host + "\"");
+ }
+ }
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final String host = origin.getHost();
+ String domain = cookie.getDomain();
+ if (domain == null) {
+ return false;
+ }
+ if (host.equals(domain)) {
+ return true;
+ }
+ if (!domain.startsWith(".")) {
+ domain = '.' + domain;
+ }
+ return host.endsWith(domain) || host.equals(domain.substring(1));
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicExpiresHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicExpiresHandler.java
new file mode 100644
index 000000000..9b9dee5b2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicExpiresHandler.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Date;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicExpiresHandler extends AbstractCookieAttributeHandler {
+
+ /** Valid date patterns */
+ private final String[] datepatterns;
+
+ public BasicExpiresHandler(final String[] datepatterns) {
+ Args.notNull(datepatterns, "Array of date patterns");
+ this.datepatterns = datepatterns;
+ }
+
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (value == null) {
+ throw new MalformedCookieException("Missing value for expires attribute");
+ }
+ final Date expiry = DateUtils.parseDate(value, this.datepatterns);
+ if (expiry == null) {
+ throw new MalformedCookieException("Unable to parse expires attribute: "
+ + value);
+ }
+ cookie.setExpiryDate(expiry);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java
new file mode 100644
index 000000000..750361b22
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Date;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicMaxAgeHandler extends AbstractCookieAttributeHandler {
+
+ public BasicMaxAgeHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (value == null) {
+ throw new MalformedCookieException("Missing value for max-age attribute");
+ }
+ final int age;
+ try {
+ age = Integer.parseInt(value);
+ } catch (final NumberFormatException e) {
+ throw new MalformedCookieException ("Invalid max-age attribute: "
+ + value);
+ }
+ if (age < 0) {
+ throw new MalformedCookieException ("Negative max-age attribute: "
+ + value);
+ }
+ cookie.setExpiryDate(new Date(System.currentTimeMillis() + age * 1000L));
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicPathHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicPathHandler.java
new file mode 100644
index 000000000..e73657148
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicPathHandler.java
@@ -0,0 +1,87 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.TextUtils;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicPathHandler implements CookieAttributeHandler {
+
+ public BasicPathHandler() {
+ super();
+ }
+
+ public void parse(
+ final SetCookie cookie, final String value) throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ cookie.setPath(!TextUtils.isBlank(value) ? value : "/");
+ }
+
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ if (!match(cookie, origin)) {
+ throw new CookieRestrictionViolationException(
+ "Illegal path attribute \"" + cookie.getPath()
+ + "\". Path of origin: \"" + origin.getPath() + "\"");
+ }
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final String targetpath = origin.getPath();
+ String topmostPath = cookie.getPath();
+ if (topmostPath == null) {
+ topmostPath = "/";
+ }
+ if (topmostPath.length() > 1 && topmostPath.endsWith("/")) {
+ topmostPath = topmostPath.substring(0, topmostPath.length() - 1);
+ }
+ boolean match = targetpath.startsWith (topmostPath);
+ // if there is a match and these values are not exactly the same we have
+ // to make sure we're not matcing "/foobar" and "/foo"
+ if (match && targetpath.length() != topmostPath.length()) {
+ if (!topmostPath.endsWith("/")) {
+ match = (targetpath.charAt(topmostPath.length()) == '/');
+ }
+ }
+ return match;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicSecureHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicSecureHandler.java
new file mode 100644
index 000000000..939741fc3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BasicSecureHandler.java
@@ -0,0 +1,60 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicSecureHandler extends AbstractCookieAttributeHandler {
+
+ public BasicSecureHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ cookie.setSecure(true);
+ }
+
+ @Override
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ return !cookie.isSecure() || origin.isSecure();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpec.java
new file mode 100644
index 000000000..bdb06090d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpec.java
@@ -0,0 +1,207 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SM;
+import ch.boye.httpclientandroidlib.cookie.SetCookie2;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * 'Meta' cookie specification that picks up a cookie policy based on
+ * the format of cookies sent with the HTTP response.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // CookieSpec fields are @NotThreadSafe
+public class BestMatchSpec implements CookieSpec {
+
+ private final String[] datepatterns;
+ private final boolean oneHeader;
+
+ // Cached values of CookieSpec instances
+ private RFC2965Spec strict; // @NotThreadSafe
+ private RFC2109Spec obsoleteStrict; // @NotThreadSafe
+ private BrowserCompatSpec compat; // @NotThreadSafe
+
+ public BestMatchSpec(final String[] datepatterns, final boolean oneHeader) {
+ super();
+ this.datepatterns = datepatterns == null ? null : datepatterns.clone();
+ this.oneHeader = oneHeader;
+ }
+
+ public BestMatchSpec() {
+ this(null, false);
+ }
+
+ private RFC2965Spec getStrict() {
+ if (this.strict == null) {
+ this.strict = new RFC2965Spec(this.datepatterns, this.oneHeader);
+ }
+ return strict;
+ }
+
+ private RFC2109Spec getObsoleteStrict() {
+ if (this.obsoleteStrict == null) {
+ this.obsoleteStrict = new RFC2109Spec(this.datepatterns, this.oneHeader);
+ }
+ return obsoleteStrict;
+ }
+
+ private BrowserCompatSpec getCompat() {
+ if (this.compat == null) {
+ this.compat = new BrowserCompatSpec(this.datepatterns);
+ }
+ return compat;
+ }
+
+ public List<Cookie> parse(
+ final Header header,
+ final CookieOrigin origin) throws MalformedCookieException {
+ Args.notNull(header, "Header");
+ Args.notNull(origin, "Cookie origin");
+ HeaderElement[] helems = header.getElements();
+ boolean versioned = false;
+ boolean netscape = false;
+ for (final HeaderElement helem: helems) {
+ if (helem.getParameterByName("version") != null) {
+ versioned = true;
+ }
+ if (helem.getParameterByName("expires") != null) {
+ netscape = true;
+ }
+ }
+ if (netscape || !versioned) {
+ // Need to parse the header again, because Netscape style cookies do not correctly
+ // support multiple header elements (comma cannot be treated as an element separator)
+ final NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT;
+ final CharArrayBuffer buffer;
+ final ParserCursor cursor;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ cursor = new ParserCursor(
+ ((FormattedHeader) header).getValuePos(),
+ buffer.length());
+ } else {
+ final String s = header.getValue();
+ if (s == null) {
+ throw new MalformedCookieException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ cursor = new ParserCursor(0, buffer.length());
+ }
+ helems = new HeaderElement[] { parser.parseHeader(buffer, cursor) };
+ return getCompat().parse(helems, origin);
+ } else {
+ if (SM.SET_COOKIE2.equals(header.getName())) {
+ return getStrict().parse(helems, origin);
+ } else {
+ return getObsoleteStrict().parse(helems, origin);
+ }
+ }
+ }
+
+ public void validate(
+ final Cookie cookie,
+ final CookieOrigin origin) throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ if (cookie.getVersion() > 0) {
+ if (cookie instanceof SetCookie2) {
+ getStrict().validate(cookie, origin);
+ } else {
+ getObsoleteStrict().validate(cookie, origin);
+ }
+ } else {
+ getCompat().validate(cookie, origin);
+ }
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ if (cookie.getVersion() > 0) {
+ if (cookie instanceof SetCookie2) {
+ return getStrict().match(cookie, origin);
+ } else {
+ return getObsoleteStrict().match(cookie, origin);
+ }
+ } else {
+ return getCompat().match(cookie, origin);
+ }
+ }
+
+ public List<Header> formatCookies(final List<Cookie> cookies) {
+ Args.notNull(cookies, "List of cookies");
+ int version = Integer.MAX_VALUE;
+ boolean isSetCookie2 = true;
+ for (final Cookie cookie: cookies) {
+ if (!(cookie instanceof SetCookie2)) {
+ isSetCookie2 = false;
+ }
+ if (cookie.getVersion() < version) {
+ version = cookie.getVersion();
+ }
+ }
+ if (version > 0) {
+ if (isSetCookie2) {
+ return getStrict().formatCookies(cookies);
+ } else {
+ return getObsoleteStrict().formatCookies(cookies);
+ }
+ } else {
+ return getCompat().formatCookies(cookies);
+ }
+ }
+
+ public int getVersion() {
+ return getStrict().getVersion();
+ }
+
+ public Header getVersionHeader() {
+ return getStrict().getVersionHeader();
+ }
+
+ @Override
+ public String toString() {
+ return "best-match";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java
new file mode 100644
index 000000000..c20e4bcd1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java
@@ -0,0 +1,86 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecFactory;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link CookieSpecProvider} implementation that creates and initializes
+ * {@link BestMatchSpec} instances.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class BestMatchSpecFactory implements CookieSpecFactory, CookieSpecProvider {
+
+ private final String[] datepatterns;
+ private final boolean oneHeader;
+
+ public BestMatchSpecFactory(final String[] datepatterns, final boolean oneHeader) {
+ super();
+ this.datepatterns = datepatterns;
+ this.oneHeader = oneHeader;
+ }
+
+ public BestMatchSpecFactory() {
+ this(null, false);
+ }
+
+ public CookieSpec newInstance(final HttpParams params) {
+ if (params != null) {
+
+ String[] patterns = null;
+ final Collection<?> param = (Collection<?>) params.getParameter(
+ CookieSpecPNames.DATE_PATTERNS);
+ if (param != null) {
+ patterns = new String[param.size()];
+ patterns = param.toArray(patterns);
+ }
+ final boolean singleHeader = params.getBooleanParameter(
+ CookieSpecPNames.SINGLE_COOKIE_HEADER, false);
+
+ return new BestMatchSpec(patterns, singleHeader);
+ } else {
+ return new BestMatchSpec();
+ }
+ }
+
+ public CookieSpec create(final HttpContext context) {
+ return new BestMatchSpec(this.datepatterns, this.oneHeader);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpec.java
new file mode 100644
index 000000000..6caa71987
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpec.java
@@ -0,0 +1,219 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SM;
+import ch.boye.httpclientandroidlib.message.BasicHeaderElement;
+import ch.boye.httpclientandroidlib.message.BasicHeaderValueFormatter;
+import ch.boye.httpclientandroidlib.message.BufferedHeader;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+
+/**
+ * Cookie specification that strives to closely mimic (mis)behavior of
+ * common web browser applications such as Microsoft Internet Explorer
+ * and Mozilla FireFox.
+ *
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // superclass is @NotThreadSafe
+public class BrowserCompatSpec extends CookieSpecBase {
+
+
+ private static final String[] DEFAULT_DATE_PATTERNS = new String[] {
+ DateUtils.PATTERN_RFC1123,
+ DateUtils.PATTERN_RFC1036,
+ DateUtils.PATTERN_ASCTIME,
+ "EEE, dd-MMM-yyyy HH:mm:ss z",
+ "EEE, dd-MMM-yyyy HH-mm-ss z",
+ "EEE, dd MMM yy HH:mm:ss z",
+ "EEE dd-MMM-yyyy HH:mm:ss z",
+ "EEE dd MMM yyyy HH:mm:ss z",
+ "EEE dd-MMM-yyyy HH-mm-ss z",
+ "EEE dd-MMM-yy HH:mm:ss z",
+ "EEE dd MMM yy HH:mm:ss z",
+ "EEE,dd-MMM-yy HH:mm:ss z",
+ "EEE,dd-MMM-yyyy HH:mm:ss z",
+ "EEE, dd-MM-yyyy HH:mm:ss z",
+ };
+
+ private final String[] datepatterns;
+
+ /** Default constructor */
+ public BrowserCompatSpec(final String[] datepatterns, final BrowserCompatSpecFactory.SecurityLevel securityLevel) {
+ super();
+ if (datepatterns != null) {
+ this.datepatterns = datepatterns.clone();
+ } else {
+ this.datepatterns = DEFAULT_DATE_PATTERNS;
+ }
+ switch (securityLevel) {
+ case SECURITYLEVEL_DEFAULT:
+ registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler());
+ break;
+ case SECURITYLEVEL_IE_MEDIUM:
+ registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler() {
+ @Override
+ public void validate(final Cookie cookie, final CookieOrigin origin) throws MalformedCookieException {
+ // No validation
+ }
+ }
+ );
+ break;
+ default:
+ throw new RuntimeException("Unknown security level");
+ }
+
+ registerAttribHandler(ClientCookie.DOMAIN_ATTR, new BasicDomainHandler());
+ registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler());
+ registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler());
+ registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler());
+ registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler(
+ this.datepatterns));
+ registerAttribHandler(ClientCookie.VERSION_ATTR, new BrowserCompatVersionAttributeHandler());
+ }
+
+ /** Default constructor */
+ public BrowserCompatSpec(final String[] datepatterns) {
+ this(datepatterns, BrowserCompatSpecFactory.SecurityLevel.SECURITYLEVEL_DEFAULT);
+ }
+
+ /** Default constructor */
+ public BrowserCompatSpec() {
+ this(null, BrowserCompatSpecFactory.SecurityLevel.SECURITYLEVEL_DEFAULT);
+ }
+
+ public List<Cookie> parse(final Header header, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(header, "Header");
+ Args.notNull(origin, "Cookie origin");
+ final String headername = header.getName();
+ if (!headername.equalsIgnoreCase(SM.SET_COOKIE)) {
+ throw new MalformedCookieException("Unrecognized cookie header '"
+ + header.toString() + "'");
+ }
+ HeaderElement[] helems = header.getElements();
+ boolean versioned = false;
+ boolean netscape = false;
+ for (final HeaderElement helem: helems) {
+ if (helem.getParameterByName("version") != null) {
+ versioned = true;
+ }
+ if (helem.getParameterByName("expires") != null) {
+ netscape = true;
+ }
+ }
+ if (netscape || !versioned) {
+ // Need to parse the header again, because Netscape style cookies do not correctly
+ // support multiple header elements (comma cannot be treated as an element separator)
+ final NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT;
+ final CharArrayBuffer buffer;
+ final ParserCursor cursor;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ cursor = new ParserCursor(
+ ((FormattedHeader) header).getValuePos(),
+ buffer.length());
+ } else {
+ final String s = header.getValue();
+ if (s == null) {
+ throw new MalformedCookieException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ cursor = new ParserCursor(0, buffer.length());
+ }
+ helems = new HeaderElement[] { parser.parseHeader(buffer, cursor) };
+ }
+ return parse(helems, origin);
+ }
+
+ private static boolean isQuoteEnclosed(final String s) {
+ return s != null && s.startsWith("\"") && s.endsWith("\"");
+ }
+
+ public List<Header> formatCookies(final List<Cookie> cookies) {
+ Args.notEmpty(cookies, "List of cookies");
+ final CharArrayBuffer buffer = new CharArrayBuffer(20 * cookies.size());
+ buffer.append(SM.COOKIE);
+ buffer.append(": ");
+ for (int i = 0; i < cookies.size(); i++) {
+ final Cookie cookie = cookies.get(i);
+ if (i > 0) {
+ buffer.append("; ");
+ }
+ final String cookieName = cookie.getName();
+ final String cookieValue = cookie.getValue();
+ if (cookie.getVersion() > 0 && !isQuoteEnclosed(cookieValue)) {
+ BasicHeaderValueFormatter.INSTANCE.formatHeaderElement(
+ buffer,
+ new BasicHeaderElement(cookieName, cookieValue),
+ false);
+ } else {
+ // Netscape style cookies do not support quoted values
+ buffer.append(cookieName);
+ buffer.append("=");
+ if (cookieValue != null) {
+ buffer.append(cookieValue);
+ }
+ }
+ }
+ final List<Header> headers = new ArrayList<Header>(1);
+ headers.add(new BufferedHeader(buffer));
+ return headers;
+ }
+
+ public int getVersion() {
+ return 0;
+ }
+
+ public Header getVersionHeader() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "compatibility";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java
new file mode 100644
index 000000000..f6239b4f3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java
@@ -0,0 +1,92 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecFactory;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link CookieSpecProvider} implementation that creates and initializes
+ * {@link BrowserCompatSpec} instances.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class BrowserCompatSpecFactory implements CookieSpecFactory, CookieSpecProvider {
+
+ public enum SecurityLevel {
+ SECURITYLEVEL_DEFAULT,
+ SECURITYLEVEL_IE_MEDIUM
+ }
+
+ private final String[] datepatterns;
+ private final SecurityLevel securityLevel;
+
+ public BrowserCompatSpecFactory(final String[] datepatterns, final SecurityLevel securityLevel) {
+ super();
+ this.datepatterns = datepatterns;
+ this.securityLevel = securityLevel;
+ }
+
+ public BrowserCompatSpecFactory(final String[] datepatterns) {
+ this(null, SecurityLevel.SECURITYLEVEL_DEFAULT);
+ }
+
+ public BrowserCompatSpecFactory() {
+ this(null, SecurityLevel.SECURITYLEVEL_DEFAULT);
+ }
+
+ public CookieSpec newInstance(final HttpParams params) {
+ if (params != null) {
+
+ String[] patterns = null;
+ final Collection<?> param = (Collection<?>) params.getParameter(
+ CookieSpecPNames.DATE_PATTERNS);
+ if (param != null) {
+ patterns = new String[param.size()];
+ patterns = param.toArray(patterns);
+ }
+ return new BrowserCompatSpec(patterns, securityLevel);
+ } else {
+ return new BrowserCompatSpec(null, securityLevel);
+ }
+ }
+
+ public CookieSpec create(final HttpContext context) {
+ return new BrowserCompatSpec(this.datepatterns);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatVersionAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatVersionAttributeHandler.java
new file mode 100644
index 000000000..210fac962
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/BrowserCompatVersionAttributeHandler.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * <tt>"Version"</tt> cookie attribute handler for BrowserCompat cookie spec.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class BrowserCompatVersionAttributeHandler extends
+ AbstractCookieAttributeHandler {
+
+ public BrowserCompatVersionAttributeHandler() {
+ super();
+ }
+
+ /**
+ * Parse cookie version attribute.
+ */
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (value == null) {
+ throw new MalformedCookieException("Missing value for version attribute");
+ }
+ int version = 0;
+ try {
+ version = Integer.parseInt(value);
+ } catch (final NumberFormatException e) {
+ // Just ignore invalid versions
+ }
+ cookie.setVersion(version);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/CookieSpecBase.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/CookieSpecBase.java
new file mode 100644
index 000000000..e59c3686e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/CookieSpecBase.java
@@ -0,0 +1,121 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Cookie management functions shared by all specification.
+ *
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // AbstractCookieSpec is not thread-safe
+public abstract class CookieSpecBase extends AbstractCookieSpec {
+
+ protected static String getDefaultPath(final CookieOrigin origin) {
+ String defaultPath = origin.getPath();
+ int lastSlashIndex = defaultPath.lastIndexOf('/');
+ if (lastSlashIndex >= 0) {
+ if (lastSlashIndex == 0) {
+ //Do not remove the very first slash
+ lastSlashIndex = 1;
+ }
+ defaultPath = defaultPath.substring(0, lastSlashIndex);
+ }
+ return defaultPath;
+ }
+
+ protected static String getDefaultDomain(final CookieOrigin origin) {
+ return origin.getHost();
+ }
+
+ protected List<Cookie> parse(final HeaderElement[] elems, final CookieOrigin origin)
+ throws MalformedCookieException {
+ final List<Cookie> cookies = new ArrayList<Cookie>(elems.length);
+ for (final HeaderElement headerelement : elems) {
+ final String name = headerelement.getName();
+ final String value = headerelement.getValue();
+ if (name == null || name.length() == 0) {
+ throw new MalformedCookieException("Cookie name may not be empty");
+ }
+
+ final BasicClientCookie cookie = new BasicClientCookie(name, value);
+ cookie.setPath(getDefaultPath(origin));
+ cookie.setDomain(getDefaultDomain(origin));
+
+ // cycle through the parameters
+ final NameValuePair[] attribs = headerelement.getParameters();
+ for (int j = attribs.length - 1; j >= 0; j--) {
+ final NameValuePair attrib = attribs[j];
+ final String s = attrib.getName().toLowerCase(Locale.ENGLISH);
+
+ cookie.setAttribute(s, attrib.getValue());
+
+ final CookieAttributeHandler handler = findAttribHandler(s);
+ if (handler != null) {
+ handler.parse(cookie, attrib.getValue());
+ }
+ }
+ cookies.add(cookie);
+ }
+ return cookies;
+ }
+
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ for (final CookieAttributeHandler handler: getAttribHandlers()) {
+ handler.validate(cookie, origin);
+ }
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ for (final CookieAttributeHandler handler: getAttribHandlers()) {
+ if (!handler.match(cookie, origin)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateParseException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateParseException.java
new file mode 100644
index 000000000..08b387272
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateParseException.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * An exception to indicate an error parsing a date string.
+ *
+ * @see DateUtils
+ *
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) no longer used.
+ */
+@Deprecated
+@Immutable
+public class DateParseException extends Exception {
+
+ private static final long serialVersionUID = 4417696455000643370L;
+
+ /**
+ *
+ */
+ public DateParseException() {
+ super();
+ }
+
+ /**
+ * @param message the exception message
+ */
+ public DateParseException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateUtils.java
new file mode 100644
index 000000000..897d6fb00
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateUtils.java
@@ -0,0 +1,156 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * A utility class for parsing and formatting HTTP dates as used in cookies and
+ * other headers. This class handles dates as defined by RFC 2616 section
+ * 3.3.1 as well as some other common non-standard formats.
+ *
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) Use {@link ch.boye.httpclientandroidlib.client.utils.DateUtils}.
+ */
+@Deprecated
+@Immutable
+public final class DateUtils {
+
+ /**
+ * Date format pattern used to parse HTTP date headers in RFC 1123 format.
+ */
+ public static final String PATTERN_RFC1123 = ch.boye.httpclientandroidlib.client.utils.DateUtils.PATTERN_RFC1123;
+
+ /**
+ * Date format pattern used to parse HTTP date headers in RFC 1036 format.
+ */
+ public static final String PATTERN_RFC1036 = ch.boye.httpclientandroidlib.client.utils.DateUtils.PATTERN_RFC1036;
+
+ /**
+ * Date format pattern used to parse HTTP date headers in ANSI C
+ * <code>asctime()</code> format.
+ */
+ public static final String PATTERN_ASCTIME = ch.boye.httpclientandroidlib.client.utils.DateUtils.PATTERN_ASCTIME;
+
+ public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
+ /**
+ * Parses a date value. The formats used for parsing the date value are retrieved from
+ * the default http params.
+ *
+ * @param dateValue the date value to parse
+ *
+ * @return the parsed date
+ *
+ * @throws DateParseException if the value could not be parsed using any of the
+ * supported date formats
+ */
+ public static Date parseDate(final String dateValue) throws DateParseException {
+ return parseDate(dateValue, null, null);
+ }
+
+ /**
+ * Parses the date value using the given date formats.
+ *
+ * @param dateValue the date value to parse
+ * @param dateFormats the date formats to use
+ *
+ * @return the parsed date
+ *
+ * @throws DateParseException if none of the dataFormats could parse the dateValue
+ */
+ public static Date parseDate(final String dateValue, final String[] dateFormats)
+ throws DateParseException {
+ return parseDate(dateValue, dateFormats, null);
+ }
+
+ /**
+ * Parses the date value using the given date formats.
+ *
+ * @param dateValue the date value to parse
+ * @param dateFormats the date formats to use
+ * @param startDate During parsing, two digit years will be placed in the range
+ * <code>startDate</code> to <code>startDate + 100 years</code>. This value may
+ * be <code>null</code>. When <code>null</code> is given as a parameter, year
+ * <code>2000</code> will be used.
+ *
+ * @return the parsed date
+ *
+ * @throws DateParseException if none of the dataFormats could parse the dateValue
+ */
+ public static Date parseDate(
+ final String dateValue,
+ final String[] dateFormats,
+ final Date startDate
+ ) throws DateParseException {
+ final Date d = ch.boye.httpclientandroidlib.client.utils.DateUtils.parseDate(dateValue, dateFormats, startDate);
+ if (d == null) {
+ throw new DateParseException("Unable to parse the date " + dateValue);
+ }
+ return d;
+ }
+
+ /**
+ * Formats the given date according to the RFC 1123 pattern.
+ *
+ * @param date The date to format.
+ * @return An RFC 1123 formatted date string.
+ *
+ * @see #PATTERN_RFC1123
+ */
+ public static String formatDate(final Date date) {
+ return ch.boye.httpclientandroidlib.client.utils.DateUtils.formatDate(date);
+ }
+
+ /**
+ * Formats the given date according to the specified pattern. The pattern
+ * must conform to that used by the {@link java.text.SimpleDateFormat simple
+ * date format} class.
+ *
+ * @param date The date to format.
+ * @param pattern The pattern to use for formatting the date.
+ * @return A formatted date string.
+ *
+ * @throws IllegalArgumentException If the given date pattern is invalid.
+ *
+ * @see java.text.SimpleDateFormat
+ */
+ public static String formatDate(final Date date, final String pattern) {
+ return ch.boye.httpclientandroidlib.client.utils.DateUtils.formatDate(date, pattern);
+ }
+
+ /** This class should not be instantiated. */
+ private DateUtils() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpec.java
new file mode 100644
index 000000000..3aa350a40
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpec.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collections;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+
+/**
+ * CookieSpec that ignores all cookies
+ *
+ * @since 4.1
+ */
+@NotThreadSafe // superclass is @NotThreadSafe
+public class IgnoreSpec extends CookieSpecBase {
+
+ public int getVersion() {
+ return 0;
+ }
+
+ public List<Cookie> parse(final Header header, final CookieOrigin origin)
+ throws MalformedCookieException {
+ return Collections.emptyList();
+ }
+
+ public List<Header> formatCookies(final List<Cookie> cookies) {
+ return Collections.emptyList();
+ }
+
+ public Header getVersionHeader() {
+ return null;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java
new file mode 100644
index 000000000..426e25cad
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java
@@ -0,0 +1,58 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecFactory;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link CookieSpecProvider} implementation that ignores all cookies.
+ *
+ * @since 4.1
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class IgnoreSpecFactory implements CookieSpecFactory, CookieSpecProvider {
+
+ public IgnoreSpecFactory() {
+ super();
+ }
+
+ public CookieSpec newInstance(final HttpParams params) {
+ return new IgnoreSpec();
+ }
+
+ public CookieSpec create(final HttpContext context) {
+ return new IgnoreSpec();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java
new file mode 100644
index 000000000..adbd40e91
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java
@@ -0,0 +1,106 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class NetscapeDomainHandler extends BasicDomainHandler {
+
+ public NetscapeDomainHandler() {
+ super();
+ }
+
+ @Override
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ super.validate(cookie, origin);
+ // Perform Netscape Cookie draft specific validation
+ final String host = origin.getHost();
+ final String domain = cookie.getDomain();
+ if (host.contains(".")) {
+ final int domainParts = new StringTokenizer(domain, ".").countTokens();
+
+ if (isSpecialDomain(domain)) {
+ if (domainParts < 2) {
+ throw new CookieRestrictionViolationException("Domain attribute \""
+ + domain
+ + "\" violates the Netscape cookie specification for "
+ + "special domains");
+ }
+ } else {
+ if (domainParts < 3) {
+ throw new CookieRestrictionViolationException("Domain attribute \""
+ + domain
+ + "\" violates the Netscape cookie specification");
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the given domain is in one of the seven special
+ * top level domains defined by the Netscape cookie specification.
+ * @param domain The domain.
+ * @return True if the specified domain is "special"
+ */
+ private static boolean isSpecialDomain(final String domain) {
+ final String ucDomain = domain.toUpperCase(Locale.ENGLISH);
+ return ucDomain.endsWith(".COM")
+ || ucDomain.endsWith(".EDU")
+ || ucDomain.endsWith(".NET")
+ || ucDomain.endsWith(".GOV")
+ || ucDomain.endsWith(".MIL")
+ || ucDomain.endsWith(".ORG")
+ || ucDomain.endsWith(".INT");
+ }
+
+ @Override
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final String host = origin.getHost();
+ final String domain = cookie.getDomain();
+ if (domain == null) {
+ return false;
+ }
+ return host.endsWith(domain);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java
new file mode 100644
index 000000000..89a59688f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java
@@ -0,0 +1,138 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.message.BasicHeaderElement;
+import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class NetscapeDraftHeaderParser {
+
+ public final static NetscapeDraftHeaderParser DEFAULT = new NetscapeDraftHeaderParser();
+
+ public NetscapeDraftHeaderParser() {
+ super();
+ }
+
+ public HeaderElement parseHeader(
+ final CharArrayBuffer buffer,
+ final ParserCursor cursor) throws ParseException {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ final NameValuePair nvp = parseNameValuePair(buffer, cursor);
+ final List<NameValuePair> params = new ArrayList<NameValuePair>();
+ while (!cursor.atEnd()) {
+ final NameValuePair param = parseNameValuePair(buffer, cursor);
+ params.add(param);
+ }
+ return new BasicHeaderElement(
+ nvp.getName(),
+ nvp.getValue(), params.toArray(new NameValuePair[params.size()]));
+ }
+
+ private NameValuePair parseNameValuePair(
+ final CharArrayBuffer buffer, final ParserCursor cursor) {
+ boolean terminated = false;
+
+ int pos = cursor.getPos();
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+
+ // Find name
+ String name = null;
+ while (pos < indexTo) {
+ final char ch = buffer.charAt(pos);
+ if (ch == '=') {
+ break;
+ }
+ if (ch == ';') {
+ terminated = true;
+ break;
+ }
+ pos++;
+ }
+
+ if (pos == indexTo) {
+ terminated = true;
+ name = buffer.substringTrimmed(indexFrom, indexTo);
+ } else {
+ name = buffer.substringTrimmed(indexFrom, pos);
+ pos++;
+ }
+
+ if (terminated) {
+ cursor.updatePos(pos);
+ return new BasicNameValuePair(name, null);
+ }
+
+ // Find value
+ String value = null;
+ int i1 = pos;
+
+ while (pos < indexTo) {
+ final char ch = buffer.charAt(pos);
+ if (ch == ';') {
+ terminated = true;
+ break;
+ }
+ pos++;
+ }
+
+ int i2 = pos;
+ // Trim leading white spaces
+ while (i1 < i2 && (HTTP.isWhitespace(buffer.charAt(i1)))) {
+ i1++;
+ }
+ // Trim trailing white spaces
+ while ((i2 > i1) && (HTTP.isWhitespace(buffer.charAt(i2 - 1)))) {
+ i2--;
+ }
+ value = buffer.substring(i1, i2);
+ if (terminated) {
+ pos++;
+ }
+ cursor.updatePos(pos);
+ return new BasicNameValuePair(name, value);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java
new file mode 100644
index 000000000..139e5985c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java
@@ -0,0 +1,171 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SM;
+import ch.boye.httpclientandroidlib.message.BufferedHeader;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * This {@link ch.boye.httpclientandroidlib.cookie.CookieSpec} implementation conforms to
+ * the original draft specification published by Netscape Communications.
+ * It should be avoided unless absolutely necessary for compatibility with
+ * legacy applications.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // superclass is @NotThreadSafe
+public class NetscapeDraftSpec extends CookieSpecBase {
+
+ protected static final String EXPIRES_PATTERN = "EEE, dd-MMM-yy HH:mm:ss z";
+
+ private final String[] datepatterns;
+
+ /** Default constructor */
+ public NetscapeDraftSpec(final String[] datepatterns) {
+ super();
+ if (datepatterns != null) {
+ this.datepatterns = datepatterns.clone();
+ } else {
+ this.datepatterns = new String[] { EXPIRES_PATTERN };
+ }
+ registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler());
+ registerAttribHandler(ClientCookie.DOMAIN_ATTR, new NetscapeDomainHandler());
+ registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler());
+ registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler());
+ registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler());
+ registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler(
+ this.datepatterns));
+ }
+
+ /** Default constructor */
+ public NetscapeDraftSpec() {
+ this(null);
+ }
+
+ /**
+ * Parses the Set-Cookie value into an array of <tt>Cookie</tt>s.
+ *
+ * <p>Syntax of the Set-Cookie HTTP Response Header:</p>
+ *
+ * <p>This is the format a CGI script would use to add to
+ * the HTTP headers a new piece of data which is to be stored by
+ * the client for later retrieval.</p>
+ *
+ * <PRE>
+ * Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
+ * </PRE>
+ *
+ * <p>Please note that the Netscape draft specification does not fully conform to the HTTP
+ * header format. Comma character if present in <code>Set-Cookie</code> will not be treated
+ * as a header element separator</p>
+ *
+ * @see <a href="http://web.archive.org/web/20020803110822/http://wp.netscape.com/newsref/std/cookie_spec.html">
+ * The Cookie Spec.</a>
+ *
+ * @param header the <tt>Set-Cookie</tt> received from the server
+ * @return an array of <tt>Cookie</tt>s parsed from the Set-Cookie value
+ * @throws MalformedCookieException if an exception occurs during parsing
+ */
+ public List<Cookie> parse(final Header header, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(header, "Header");
+ Args.notNull(origin, "Cookie origin");
+ if (!header.getName().equalsIgnoreCase(SM.SET_COOKIE)) {
+ throw new MalformedCookieException("Unrecognized cookie header '"
+ + header.toString() + "'");
+ }
+ final NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT;
+ final CharArrayBuffer buffer;
+ final ParserCursor cursor;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ cursor = new ParserCursor(
+ ((FormattedHeader) header).getValuePos(),
+ buffer.length());
+ } else {
+ final String s = header.getValue();
+ if (s == null) {
+ throw new MalformedCookieException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ cursor = new ParserCursor(0, buffer.length());
+ }
+ return parse(new HeaderElement[] { parser.parseHeader(buffer, cursor) }, origin);
+ }
+
+ public List<Header> formatCookies(final List<Cookie> cookies) {
+ Args.notEmpty(cookies, "List of cookies");
+ final CharArrayBuffer buffer = new CharArrayBuffer(20 * cookies.size());
+ buffer.append(SM.COOKIE);
+ buffer.append(": ");
+ for (int i = 0; i < cookies.size(); i++) {
+ final Cookie cookie = cookies.get(i);
+ if (i > 0) {
+ buffer.append("; ");
+ }
+ buffer.append(cookie.getName());
+ final String s = cookie.getValue();
+ if (s != null) {
+ buffer.append("=");
+ buffer.append(s);
+ }
+ }
+ final List<Header> headers = new ArrayList<Header>(1);
+ headers.add(new BufferedHeader(buffer));
+ return headers;
+ }
+
+ public int getVersion() {
+ return 0;
+ }
+
+ public Header getVersionHeader() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "netscape";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java
new file mode 100644
index 000000000..d1187a150
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecFactory;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link CookieSpecProvider} implementation that creates and initializes
+ * {@link NetscapeDraftSpec} instances.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class NetscapeDraftSpecFactory implements CookieSpecFactory, CookieSpecProvider {
+
+ private final String[] datepatterns;
+
+ public NetscapeDraftSpecFactory(final String[] datepatterns) {
+ super();
+ this.datepatterns = datepatterns;
+ }
+
+ public NetscapeDraftSpecFactory() {
+ this(null);
+ }
+
+ public CookieSpec newInstance(final HttpParams params) {
+ if (params != null) {
+
+ String[] patterns = null;
+ final Collection<?> param = (Collection<?>) params.getParameter(
+ CookieSpecPNames.DATE_PATTERNS);
+ if (param != null) {
+ patterns = new String[param.size()];
+ patterns = param.toArray(patterns);
+ }
+ return new NetscapeDraftSpec(patterns);
+ } else {
+ return new NetscapeDraftSpec();
+ }
+ }
+
+ public CookieSpec create(final HttpContext context) {
+ return new NetscapeDraftSpec(this.datepatterns);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixFilter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixFilter.java
new file mode 100644
index 000000000..4777918ba
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixFilter.java
@@ -0,0 +1,132 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import ch.boye.httpclientandroidlib.client.utils.Punycode;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+
+/**
+ * Wraps a CookieAttributeHandler and leverages its match method
+ * to never match a suffix from a black list. May be used to provide
+ * additional security for cross-site attack types by preventing
+ * cookies from apparent domains that are not publicly available.
+ * An uptodate list of suffixes can be obtained from
+ * <a href="http://publicsuffix.org/">publicsuffix.org</a>
+ *
+ * @since 4.0
+ */
+public class PublicSuffixFilter implements CookieAttributeHandler {
+ private final CookieAttributeHandler wrapped;
+ private Set<String> exceptions;
+ private Set<String> suffixes;
+
+ public PublicSuffixFilter(final CookieAttributeHandler wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ /**
+ * Sets the suffix blacklist patterns.
+ * A pattern can be "com", "*.jp"
+ * TODO add support for patterns like "lib.*.us"
+ * @param suffixes
+ */
+ public void setPublicSuffixes(final Collection<String> suffixes) {
+ this.suffixes = new HashSet<String>(suffixes);
+ }
+
+ /**
+ * Sets the exceptions from the blacklist. Exceptions can not be patterns.
+ * TODO add support for patterns
+ * @param exceptions
+ */
+ public void setExceptions(final Collection<String> exceptions) {
+ this.exceptions = new HashSet<String>(exceptions);
+ }
+
+ /**
+ * Never matches if the cookie's domain is from the blacklist.
+ */
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ if (isForPublicSuffix(cookie)) {
+ return false;
+ }
+ return wrapped.match(cookie, origin);
+ }
+
+ public void parse(final SetCookie cookie, final String value) throws MalformedCookieException {
+ wrapped.parse(cookie, value);
+ }
+
+ public void validate(final Cookie cookie, final CookieOrigin origin) throws MalformedCookieException {
+ wrapped.validate(cookie, origin);
+ }
+
+ private boolean isForPublicSuffix(final Cookie cookie) {
+ String domain = cookie.getDomain();
+ if (domain.startsWith(".")) {
+ domain = domain.substring(1);
+ }
+ domain = Punycode.toUnicode(domain);
+
+ // An exception rule takes priority over any other matching rule.
+ if (this.exceptions != null) {
+ if (this.exceptions.contains(domain)) {
+ return false;
+ }
+ }
+
+
+ if (this.suffixes == null) {
+ return false;
+ }
+
+ do {
+ if (this.suffixes.contains(domain)) {
+ return true;
+ }
+ // patterns
+ if (domain.startsWith("*.")) {
+ domain = domain.substring(2);
+ }
+ final int nextdot = domain.indexOf('.');
+ if (nextdot == -1) {
+ break;
+ }
+ domain = "*" + domain.substring(nextdot);
+ } while (domain.length() > 0);
+
+ return false;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixListParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixListParser.java
new file mode 100644
index 000000000..4f0374f99
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/PublicSuffixListParser.java
@@ -0,0 +1,127 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Parses the list from <a href="http://publicsuffix.org/">publicsuffix.org</a>
+ * and configures a PublicSuffixFilter.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class PublicSuffixListParser {
+ private static final int MAX_LINE_LEN = 256;
+ private final PublicSuffixFilter filter;
+
+ PublicSuffixListParser(final PublicSuffixFilter filter) {
+ this.filter = filter;
+ }
+
+ /**
+ * Parses the public suffix list format.
+ * When creating the reader from the file, make sure to
+ * use the correct encoding (the original list is in UTF-8).
+ *
+ * @param list the suffix list. The caller is responsible for closing the reader.
+ * @throws IOException on error while reading from list
+ */
+ public void parse(final Reader list) throws IOException {
+ final Collection<String> rules = new ArrayList<String>();
+ final Collection<String> exceptions = new ArrayList<String>();
+ final BufferedReader r = new BufferedReader(list);
+ final StringBuilder sb = new StringBuilder(256);
+ boolean more = true;
+ while (more) {
+ more = readLine(r, sb);
+ String line = sb.toString();
+ if (line.length() == 0) {
+ continue;
+ }
+ if (line.startsWith("//"))
+ {
+ continue; //entire lines can also be commented using //
+ }
+ if (line.startsWith("."))
+ {
+ line = line.substring(1); // A leading dot is optional
+ }
+ // An exclamation mark (!) at the start of a rule marks an exception to a previous wildcard rule
+ final boolean isException = line.startsWith("!");
+ if (isException) {
+ line = line.substring(1);
+ }
+
+ if (isException) {
+ exceptions.add(line);
+ } else {
+ rules.add(line);
+ }
+ }
+
+ filter.setPublicSuffixes(rules);
+ filter.setExceptions(exceptions);
+ }
+
+ /**
+ *
+ * @param r
+ * @param sb
+ * @return false when the end of the stream is reached
+ * @throws IOException
+ */
+ private boolean readLine(final Reader r, final StringBuilder sb) throws IOException {
+ sb.setLength(0);
+ int b;
+ boolean hitWhitespace = false;
+ while ((b = r.read()) != -1) {
+ final char c = (char) b;
+ if (c == '\n') {
+ break;
+ }
+ // Each line is only read up to the first whitespace
+ if (Character.isWhitespace(c)) {
+ hitWhitespace = true;
+ }
+ if (!hitWhitespace) {
+ sb.append(c);
+ }
+ if (sb.length() > MAX_LINE_LEN)
+ {
+ throw new IOException("Line too long"); // prevent excess memory usage
+ }
+ }
+ return (b != -1);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java
new file mode 100644
index 000000000..d669dcb43
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java
@@ -0,0 +1,120 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RFC2109DomainHandler implements CookieAttributeHandler {
+
+ public RFC2109DomainHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (value == null) {
+ throw new MalformedCookieException("Missing value for domain attribute");
+ }
+ if (value.trim().length() == 0) {
+ throw new MalformedCookieException("Blank value for domain attribute");
+ }
+ cookie.setDomain(value);
+ }
+
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ String host = origin.getHost();
+ final String domain = cookie.getDomain();
+ if (domain == null) {
+ throw new CookieRestrictionViolationException("Cookie domain may not be null");
+ }
+ if (!domain.equals(host)) {
+ int dotIndex = domain.indexOf('.');
+ if (dotIndex == -1) {
+ throw new CookieRestrictionViolationException("Domain attribute \""
+ + domain
+ + "\" does not match the host \""
+ + host + "\"");
+ }
+ // domain must start with dot
+ if (!domain.startsWith(".")) {
+ throw new CookieRestrictionViolationException("Domain attribute \""
+ + domain
+ + "\" violates RFC 2109: domain must start with a dot");
+ }
+ // domain must have at least one embedded dot
+ dotIndex = domain.indexOf('.', 1);
+ if (dotIndex < 0 || dotIndex == domain.length() - 1) {
+ throw new CookieRestrictionViolationException("Domain attribute \""
+ + domain
+ + "\" violates RFC 2109: domain must contain an embedded dot");
+ }
+ host = host.toLowerCase(Locale.ENGLISH);
+ if (!host.endsWith(domain)) {
+ throw new CookieRestrictionViolationException(
+ "Illegal domain attribute \"" + domain
+ + "\". Domain of origin: \"" + host + "\"");
+ }
+ // host minus domain may not contain any dots
+ final String hostWithoutDomain = host.substring(0, host.length() - domain.length());
+ if (hostWithoutDomain.indexOf('.') != -1) {
+ throw new CookieRestrictionViolationException("Domain attribute \""
+ + domain
+ + "\" violates RFC 2109: host minus domain may not contain any dots");
+ }
+ }
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final String host = origin.getHost();
+ final String domain = cookie.getDomain();
+ if (domain == null) {
+ return false;
+ }
+ return host.equals(domain) || (domain.startsWith(".") && host.endsWith(domain));
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109Spec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109Spec.java
new file mode 100644
index 000000000..1292788a0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109Spec.java
@@ -0,0 +1,240 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.utils.DateUtils;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookiePathComparator;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SM;
+import ch.boye.httpclientandroidlib.message.BufferedHeader;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * RFC 2109 compliant {@link ch.boye.httpclientandroidlib.cookie.CookieSpec} implementation.
+ * This is an older version of the official HTTP state management specification
+ * superseded by RFC 2965.
+ *
+ * @see RFC2965Spec
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // superclass is @NotThreadSafe
+public class RFC2109Spec extends CookieSpecBase {
+
+ private final static CookiePathComparator PATH_COMPARATOR = new CookiePathComparator();
+
+ private final static String[] DATE_PATTERNS = {
+ DateUtils.PATTERN_RFC1123,
+ DateUtils.PATTERN_RFC1036,
+ DateUtils.PATTERN_ASCTIME
+ };
+
+ private final String[] datepatterns;
+ private final boolean oneHeader;
+
+ /** Default constructor */
+ public RFC2109Spec(final String[] datepatterns, final boolean oneHeader) {
+ super();
+ if (datepatterns != null) {
+ this.datepatterns = datepatterns.clone();
+ } else {
+ this.datepatterns = DATE_PATTERNS;
+ }
+ this.oneHeader = oneHeader;
+ registerAttribHandler(ClientCookie.VERSION_ATTR, new RFC2109VersionHandler());
+ registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler());
+ registerAttribHandler(ClientCookie.DOMAIN_ATTR, new RFC2109DomainHandler());
+ registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler());
+ registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler());
+ registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler());
+ registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler(
+ this.datepatterns));
+ }
+
+ /** Default constructor */
+ public RFC2109Spec() {
+ this(null, false);
+ }
+
+ public List<Cookie> parse(final Header header, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(header, "Header");
+ Args.notNull(origin, "Cookie origin");
+ if (!header.getName().equalsIgnoreCase(SM.SET_COOKIE)) {
+ throw new MalformedCookieException("Unrecognized cookie header '"
+ + header.toString() + "'");
+ }
+ final HeaderElement[] elems = header.getElements();
+ return parse(elems, origin);
+ }
+
+ @Override
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ final String name = cookie.getName();
+ if (name.indexOf(' ') != -1) {
+ throw new CookieRestrictionViolationException("Cookie name may not contain blanks");
+ }
+ if (name.startsWith("$")) {
+ throw new CookieRestrictionViolationException("Cookie name may not start with $");
+ }
+ super.validate(cookie, origin);
+ }
+
+ public List<Header> formatCookies(final List<Cookie> cookies) {
+ Args.notEmpty(cookies, "List of cookies");
+ List<Cookie> cookieList;
+ if (cookies.size() > 1) {
+ // Create a mutable copy and sort the copy.
+ cookieList = new ArrayList<Cookie>(cookies);
+ Collections.sort(cookieList, PATH_COMPARATOR);
+ } else {
+ cookieList = cookies;
+ }
+ if (this.oneHeader) {
+ return doFormatOneHeader(cookieList);
+ } else {
+ return doFormatManyHeaders(cookieList);
+ }
+ }
+
+ private List<Header> doFormatOneHeader(final List<Cookie> cookies) {
+ int version = Integer.MAX_VALUE;
+ // Pick the lowest common denominator
+ for (final Cookie cookie : cookies) {
+ if (cookie.getVersion() < version) {
+ version = cookie.getVersion();
+ }
+ }
+ final CharArrayBuffer buffer = new CharArrayBuffer(40 * cookies.size());
+ buffer.append(SM.COOKIE);
+ buffer.append(": ");
+ buffer.append("$Version=");
+ buffer.append(Integer.toString(version));
+ for (final Cookie cooky : cookies) {
+ buffer.append("; ");
+ final Cookie cookie = cooky;
+ formatCookieAsVer(buffer, cookie, version);
+ }
+ final List<Header> headers = new ArrayList<Header>(1);
+ headers.add(new BufferedHeader(buffer));
+ return headers;
+ }
+
+ private List<Header> doFormatManyHeaders(final List<Cookie> cookies) {
+ final List<Header> headers = new ArrayList<Header>(cookies.size());
+ for (final Cookie cookie : cookies) {
+ final int version = cookie.getVersion();
+ final CharArrayBuffer buffer = new CharArrayBuffer(40);
+ buffer.append("Cookie: ");
+ buffer.append("$Version=");
+ buffer.append(Integer.toString(version));
+ buffer.append("; ");
+ formatCookieAsVer(buffer, cookie, version);
+ headers.add(new BufferedHeader(buffer));
+ }
+ return headers;
+ }
+
+ /**
+ * Return a name/value string suitable for sending in a <tt>"Cookie"</tt>
+ * header as defined in RFC 2109 for backward compatibility with cookie
+ * version 0
+ * @param buffer The char array buffer to use for output
+ * @param name The cookie name
+ * @param value The cookie value
+ * @param version The cookie version
+ */
+ protected void formatParamAsVer(final CharArrayBuffer buffer,
+ final String name, final String value, final int version) {
+ buffer.append(name);
+ buffer.append("=");
+ if (value != null) {
+ if (version > 0) {
+ buffer.append('\"');
+ buffer.append(value);
+ buffer.append('\"');
+ } else {
+ buffer.append(value);
+ }
+ }
+ }
+
+ /**
+ * Return a string suitable for sending in a <tt>"Cookie"</tt> header
+ * as defined in RFC 2109 for backward compatibility with cookie version 0
+ * @param buffer The char array buffer to use for output
+ * @param cookie The {@link Cookie} to be formatted as string
+ * @param version The version to use.
+ */
+ protected void formatCookieAsVer(final CharArrayBuffer buffer,
+ final Cookie cookie, final int version) {
+ formatParamAsVer(buffer, cookie.getName(), cookie.getValue(), version);
+ if (cookie.getPath() != null) {
+ if (cookie instanceof ClientCookie
+ && ((ClientCookie) cookie).containsAttribute(ClientCookie.PATH_ATTR)) {
+ buffer.append("; ");
+ formatParamAsVer(buffer, "$Path", cookie.getPath(), version);
+ }
+ }
+ if (cookie.getDomain() != null) {
+ if (cookie instanceof ClientCookie
+ && ((ClientCookie) cookie).containsAttribute(ClientCookie.DOMAIN_ATTR)) {
+ buffer.append("; ");
+ formatParamAsVer(buffer, "$Domain", cookie.getDomain(), version);
+ }
+ }
+ }
+
+ public int getVersion() {
+ return 1;
+ }
+
+ public Header getVersionHeader() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "rfc2109";
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java
new file mode 100644
index 000000000..24802c351
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java
@@ -0,0 +1,86 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecFactory;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link CookieSpecProvider} implementation that creates and initializes
+ * {@link RFC2109Spec} instances.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class RFC2109SpecFactory implements CookieSpecFactory, CookieSpecProvider {
+
+ private final String[] datepatterns;
+ private final boolean oneHeader;
+
+ public RFC2109SpecFactory(final String[] datepatterns, final boolean oneHeader) {
+ super();
+ this.datepatterns = datepatterns;
+ this.oneHeader = oneHeader;
+ }
+
+ public RFC2109SpecFactory() {
+ this(null, false);
+ }
+
+ public CookieSpec newInstance(final HttpParams params) {
+ if (params != null) {
+
+ String[] patterns = null;
+ final Collection<?> param = (Collection<?>) params.getParameter(
+ CookieSpecPNames.DATE_PATTERNS);
+ if (param != null) {
+ patterns = new String[param.size()];
+ patterns = param.toArray(patterns);
+ }
+ final boolean singleHeader = params.getBooleanParameter(
+ CookieSpecPNames.SINGLE_COOKIE_HEADER, false);
+
+ return new RFC2109Spec(patterns, singleHeader);
+ } else {
+ return new RFC2109Spec();
+ }
+ }
+
+ public CookieSpec create(final HttpContext context) {
+ return new RFC2109Spec(this.datepatterns, this.oneHeader);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java
new file mode 100644
index 000000000..a43fe9b22
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RFC2109VersionHandler extends AbstractCookieAttributeHandler {
+
+ public RFC2109VersionHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (value == null) {
+ throw new MalformedCookieException("Missing value for version attribute");
+ }
+ if (value.trim().length() == 0) {
+ throw new MalformedCookieException("Blank value for version attribute");
+ }
+ try {
+ cookie.setVersion(Integer.parseInt(value));
+ } catch (final NumberFormatException e) {
+ throw new MalformedCookieException("Invalid version: "
+ + e.getMessage());
+ }
+ }
+
+ @Override
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (cookie.getVersion() < 0) {
+ throw new CookieRestrictionViolationException("Cookie version may not be negative");
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java
new file mode 100644
index 000000000..10f5f40ec
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.cookie.SetCookie2;
+
+/**
+ * <tt>"CommentURL"</tt> cookie attribute handler for RFC 2965 cookie spec.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RFC2965CommentUrlAttributeHandler implements CookieAttributeHandler {
+
+ public RFC2965CommentUrlAttributeHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String commenturl)
+ throws MalformedCookieException {
+ if (cookie instanceof SetCookie2) {
+ final SetCookie2 cookie2 = (SetCookie2) cookie;
+ cookie2.setCommentURL(commenturl);
+ }
+ }
+
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ return true;
+ }
+
+ }
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java
new file mode 100644
index 000000000..c4bfca460
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.cookie.SetCookie2;
+
+/**
+ * <tt>"Discard"</tt> cookie attribute handler for RFC 2965 cookie spec.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RFC2965DiscardAttributeHandler implements CookieAttributeHandler {
+
+ public RFC2965DiscardAttributeHandler() {
+ super();
+ }
+
+ public void parse(final SetCookie cookie, final String commenturl)
+ throws MalformedCookieException {
+ if (cookie instanceof SetCookie2) {
+ final SetCookie2 cookie2 = (SetCookie2) cookie;
+ cookie2.setDiscard(true);
+ }
+ }
+
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ return true;
+ }
+
+ }
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java
new file mode 100644
index 000000000..62c947c55
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java
@@ -0,0 +1,185 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * <tt>"Domain"</tt> cookie attribute handler for RFC 2965 cookie spec.
+ *
+ *
+ * @since 3.1
+ */
+@Immutable
+public class RFC2965DomainAttributeHandler implements CookieAttributeHandler {
+
+ public RFC2965DomainAttributeHandler() {
+ super();
+ }
+
+ /**
+ * Parse cookie domain attribute.
+ */
+ public void parse(
+ final SetCookie cookie, final String domain) throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (domain == null) {
+ throw new MalformedCookieException(
+ "Missing value for domain attribute");
+ }
+ if (domain.trim().length() == 0) {
+ throw new MalformedCookieException(
+ "Blank value for domain attribute");
+ }
+ String s = domain;
+ s = s.toLowerCase(Locale.ENGLISH);
+ if (!domain.startsWith(".")) {
+ // Per RFC 2965 section 3.2.2
+ // "... If an explicitly specified value does not start with
+ // a dot, the user agent supplies a leading dot ..."
+ // That effectively implies that the domain attribute
+ // MAY NOT be an IP address of a host name
+ s = '.' + s;
+ }
+ cookie.setDomain(s);
+ }
+
+ /**
+ * Performs domain-match as defined by the RFC2965.
+ * <p>
+ * Host A's name domain-matches host B's if
+ * <ol>
+ * <ul>their host name strings string-compare equal; or</ul>
+ * <ul>A is a HDN string and has the form NB, where N is a non-empty
+ * name string, B has the form .B', and B' is a HDN string. (So,
+ * x.y.com domain-matches .Y.com but not Y.com.)</ul>
+ * </ol>
+ *
+ * @param host host name where cookie is received from or being sent to.
+ * @param domain The cookie domain attribute.
+ * @return true if the specified host matches the given domain.
+ */
+ public boolean domainMatch(final String host, final String domain) {
+ final boolean match = host.equals(domain)
+ || (domain.startsWith(".") && host.endsWith(domain));
+
+ return match;
+ }
+
+ /**
+ * Validate cookie domain attribute.
+ */
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final String host = origin.getHost().toLowerCase(Locale.ENGLISH);
+ if (cookie.getDomain() == null) {
+ throw new CookieRestrictionViolationException("Invalid cookie state: " +
+ "domain not specified");
+ }
+ final String cookieDomain = cookie.getDomain().toLowerCase(Locale.ENGLISH);
+
+ if (cookie instanceof ClientCookie
+ && ((ClientCookie) cookie).containsAttribute(ClientCookie.DOMAIN_ATTR)) {
+ // Domain attribute must start with a dot
+ if (!cookieDomain.startsWith(".")) {
+ throw new CookieRestrictionViolationException("Domain attribute \"" +
+ cookie.getDomain() + "\" violates RFC 2109: domain must start with a dot");
+ }
+
+ // Domain attribute must contain at least one embedded dot,
+ // or the value must be equal to .local.
+ final int dotIndex = cookieDomain.indexOf('.', 1);
+ if (((dotIndex < 0) || (dotIndex == cookieDomain.length() - 1))
+ && (!cookieDomain.equals(".local"))) {
+ throw new CookieRestrictionViolationException(
+ "Domain attribute \"" + cookie.getDomain()
+ + "\" violates RFC 2965: the value contains no embedded dots "
+ + "and the value is not .local");
+ }
+
+ // The effective host name must domain-match domain attribute.
+ if (!domainMatch(host, cookieDomain)) {
+ throw new CookieRestrictionViolationException(
+ "Domain attribute \"" + cookie.getDomain()
+ + "\" violates RFC 2965: effective host name does not "
+ + "domain-match domain attribute.");
+ }
+
+ // effective host name minus domain must not contain any dots
+ final String effectiveHostWithoutDomain = host.substring(
+ 0, host.length() - cookieDomain.length());
+ if (effectiveHostWithoutDomain.indexOf('.') != -1) {
+ throw new CookieRestrictionViolationException("Domain attribute \""
+ + cookie.getDomain() + "\" violates RFC 2965: "
+ + "effective host minus domain may not contain any dots");
+ }
+ } else {
+ // Domain was not specified in header. In this case, domain must
+ // string match request host (case-insensitive).
+ if (!cookie.getDomain().equals(host)) {
+ throw new CookieRestrictionViolationException("Illegal domain attribute: \""
+ + cookie.getDomain() + "\"."
+ + "Domain of origin: \""
+ + host + "\"");
+ }
+ }
+ }
+
+ /**
+ * Match cookie domain attribute.
+ */
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final String host = origin.getHost().toLowerCase(Locale.ENGLISH);
+ final String cookieDomain = cookie.getDomain();
+
+ // The effective host name MUST domain-match the Domain
+ // attribute of the cookie.
+ if (!domainMatch(host, cookieDomain)) {
+ return false;
+ }
+ // effective host name minus domain must not contain any dots
+ final String effectiveHostWithoutDomain = host.substring(
+ 0, host.length() - cookieDomain.length());
+ return effectiveHostWithoutDomain.indexOf('.') == -1;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java
new file mode 100644
index 000000000..4835d8eb5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java
@@ -0,0 +1,160 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.StringTokenizer;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.cookie.SetCookie2;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * <tt>"Port"</tt> cookie attribute handler for RFC 2965 cookie spec.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RFC2965PortAttributeHandler implements CookieAttributeHandler {
+
+ public RFC2965PortAttributeHandler() {
+ super();
+ }
+
+ /**
+ * Parses the given Port attribute value (e.g. "8000,8001,8002")
+ * into an array of ports.
+ *
+ * @param portValue port attribute value
+ * @return parsed array of ports
+ * @throws MalformedCookieException if there is a problem in
+ * parsing due to invalid portValue.
+ */
+ private static int[] parsePortAttribute(final String portValue)
+ throws MalformedCookieException {
+ final StringTokenizer st = new StringTokenizer(portValue, ",");
+ final int[] ports = new int[st.countTokens()];
+ try {
+ int i = 0;
+ while(st.hasMoreTokens()) {
+ ports[i] = Integer.parseInt(st.nextToken().trim());
+ if (ports[i] < 0) {
+ throw new MalformedCookieException ("Invalid Port attribute.");
+ }
+ ++i;
+ }
+ } catch (final NumberFormatException e) {
+ throw new MalformedCookieException ("Invalid Port "
+ + "attribute: " + e.getMessage());
+ }
+ return ports;
+ }
+
+ /**
+ * Returns <tt>true</tt> if the given port exists in the given
+ * ports list.
+ *
+ * @param port port of host where cookie was received from or being sent to.
+ * @param ports port list
+ * @return true returns <tt>true</tt> if the given port exists in
+ * the given ports list; <tt>false</tt> otherwise.
+ */
+ private static boolean portMatch(final int port, final int[] ports) {
+ boolean portInList = false;
+ for (final int port2 : ports) {
+ if (port == port2) {
+ portInList = true;
+ break;
+ }
+ }
+ return portInList;
+ }
+
+ /**
+ * Parse cookie port attribute.
+ */
+ public void parse(final SetCookie cookie, final String portValue)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (cookie instanceof SetCookie2) {
+ final SetCookie2 cookie2 = (SetCookie2) cookie;
+ if (portValue != null && portValue.trim().length() > 0) {
+ final int[] ports = parsePortAttribute(portValue);
+ cookie2.setPorts(ports);
+ }
+ }
+ }
+
+ /**
+ * Validate cookie port attribute. If the Port attribute was specified
+ * in header, the request port must be in cookie's port list.
+ */
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final int port = origin.getPort();
+ if (cookie instanceof ClientCookie
+ && ((ClientCookie) cookie).containsAttribute(ClientCookie.PORT_ATTR)) {
+ if (!portMatch(port, cookie.getPorts())) {
+ throw new CookieRestrictionViolationException(
+ "Port attribute violates RFC 2965: "
+ + "Request port not found in cookie's port list.");
+ }
+ }
+ }
+
+ /**
+ * Match cookie port attribute. If the Port attribute is not specified
+ * in header, the cookie can be sent to any port. Otherwise, the request port
+ * must be in the cookie's port list.
+ */
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ final int port = origin.getPort();
+ if (cookie instanceof ClientCookie
+ && ((ClientCookie) cookie).containsAttribute(ClientCookie.PORT_ATTR)) {
+ if (cookie.getPorts() == null) {
+ // Invalid cookie state: port not specified
+ return false;
+ }
+ if (!portMatch(port, cookie.getPorts())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965Spec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965Spec.java
new file mode 100644
index 000000000..1c0dbc4cb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965Spec.java
@@ -0,0 +1,239 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SM;
+import ch.boye.httpclientandroidlib.message.BufferedHeader;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * RFC 2965 compliant {@link ch.boye.httpclientandroidlib.cookie.CookieSpec} implementation.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe // superclass is @NotThreadSafe
+public class RFC2965Spec extends RFC2109Spec {
+
+ /**
+ * Default constructor
+ *
+ */
+ public RFC2965Spec() {
+ this(null, false);
+ }
+
+ public RFC2965Spec(final String[] datepatterns, final boolean oneHeader) {
+ super(datepatterns, oneHeader);
+ registerAttribHandler(ClientCookie.DOMAIN_ATTR, new RFC2965DomainAttributeHandler());
+ registerAttribHandler(ClientCookie.PORT_ATTR, new RFC2965PortAttributeHandler());
+ registerAttribHandler(ClientCookie.COMMENTURL_ATTR, new RFC2965CommentUrlAttributeHandler());
+ registerAttribHandler(ClientCookie.DISCARD_ATTR, new RFC2965DiscardAttributeHandler());
+ registerAttribHandler(ClientCookie.VERSION_ATTR, new RFC2965VersionAttributeHandler());
+ }
+
+ @Override
+ public List<Cookie> parse(
+ final Header header,
+ final CookieOrigin origin) throws MalformedCookieException {
+ Args.notNull(header, "Header");
+ Args.notNull(origin, "Cookie origin");
+ if (!header.getName().equalsIgnoreCase(SM.SET_COOKIE2)) {
+ throw new MalformedCookieException("Unrecognized cookie header '"
+ + header.toString() + "'");
+ }
+ final HeaderElement[] elems = header.getElements();
+ return createCookies(elems, adjustEffectiveHost(origin));
+ }
+
+ @Override
+ protected List<Cookie> parse(
+ final HeaderElement[] elems,
+ final CookieOrigin origin) throws MalformedCookieException {
+ return createCookies(elems, adjustEffectiveHost(origin));
+ }
+
+ private List<Cookie> createCookies(
+ final HeaderElement[] elems,
+ final CookieOrigin origin) throws MalformedCookieException {
+ final List<Cookie> cookies = new ArrayList<Cookie>(elems.length);
+ for (final HeaderElement headerelement : elems) {
+ final String name = headerelement.getName();
+ final String value = headerelement.getValue();
+ if (name == null || name.length() == 0) {
+ throw new MalformedCookieException("Cookie name may not be empty");
+ }
+
+ final BasicClientCookie2 cookie = new BasicClientCookie2(name, value);
+ cookie.setPath(getDefaultPath(origin));
+ cookie.setDomain(getDefaultDomain(origin));
+ cookie.setPorts(new int [] { origin.getPort() });
+ // cycle through the parameters
+ final NameValuePair[] attribs = headerelement.getParameters();
+
+ // Eliminate duplicate attributes. The first occurrence takes precedence
+ // See RFC2965: 3.2 Origin Server Role
+ final Map<String, NameValuePair> attribmap =
+ new HashMap<String, NameValuePair>(attribs.length);
+ for (int j = attribs.length - 1; j >= 0; j--) {
+ final NameValuePair param = attribs[j];
+ attribmap.put(param.getName().toLowerCase(Locale.ENGLISH), param);
+ }
+ for (final Map.Entry<String, NameValuePair> entry : attribmap.entrySet()) {
+ final NameValuePair attrib = entry.getValue();
+ final String s = attrib.getName().toLowerCase(Locale.ENGLISH);
+
+ cookie.setAttribute(s, attrib.getValue());
+
+ final CookieAttributeHandler handler = findAttribHandler(s);
+ if (handler != null) {
+ handler.parse(cookie, attrib.getValue());
+ }
+ }
+ cookies.add(cookie);
+ }
+ return cookies;
+ }
+
+ @Override
+ public void validate(
+ final Cookie cookie, final CookieOrigin origin) throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ super.validate(cookie, adjustEffectiveHost(origin));
+ }
+
+ @Override
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ Args.notNull(cookie, "Cookie");
+ Args.notNull(origin, "Cookie origin");
+ return super.match(cookie, adjustEffectiveHost(origin));
+ }
+
+ /**
+ * Adds valid Port attribute value, e.g. "8000,8001,8002"
+ */
+ @Override
+ protected void formatCookieAsVer(final CharArrayBuffer buffer,
+ final Cookie cookie, final int version) {
+ super.formatCookieAsVer(buffer, cookie, version);
+ // format port attribute
+ if (cookie instanceof ClientCookie) {
+ // Test if the port attribute as set by the origin server is not blank
+ final String s = ((ClientCookie) cookie).getAttribute(ClientCookie.PORT_ATTR);
+ if (s != null) {
+ buffer.append("; $Port");
+ buffer.append("=\"");
+ if (s.trim().length() > 0) {
+ final int[] ports = cookie.getPorts();
+ if (ports != null) {
+ final int len = ports.length;
+ for (int i = 0; i < len; i++) {
+ if (i > 0) {
+ buffer.append(",");
+ }
+ buffer.append(Integer.toString(ports[i]));
+ }
+ }
+ }
+ buffer.append("\"");
+ }
+ }
+ }
+
+ /**
+ * Set 'effective host name' as defined in RFC 2965.
+ * <p>
+ * If a host name contains no dots, the effective host name is
+ * that name with the string .local appended to it. Otherwise
+ * the effective host name is the same as the host name. Note
+ * that all effective host names contain at least one dot.
+ *
+ * @param origin origin where cookie is received from or being sent to.
+ */
+ private static CookieOrigin adjustEffectiveHost(final CookieOrigin origin) {
+ String host = origin.getHost();
+
+ // Test if the host name appears to be a fully qualified DNS name,
+ // IPv4 address or IPv6 address
+ boolean isLocalHost = true;
+ for (int i = 0; i < host.length(); i++) {
+ final char ch = host.charAt(i);
+ if (ch == '.' || ch == ':') {
+ isLocalHost = false;
+ break;
+ }
+ }
+ if (isLocalHost) {
+ host += ".local";
+ return new CookieOrigin(
+ host,
+ origin.getPort(),
+ origin.getPath(),
+ origin.isSecure());
+ } else {
+ return origin;
+ }
+ }
+
+ @Override
+ public int getVersion() {
+ return 1;
+ }
+
+ @Override
+ public Header getVersionHeader() {
+ final CharArrayBuffer buffer = new CharArrayBuffer(40);
+ buffer.append(SM.COOKIE2);
+ buffer.append(": ");
+ buffer.append("$Version=");
+ buffer.append(Integer.toString(getVersion()));
+ return new BufferedHeader(buffer);
+ }
+
+ @Override
+ public String toString() {
+ return "rfc2965";
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java
new file mode 100644
index 000000000..83b60407c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java
@@ -0,0 +1,86 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import java.util.Collection;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.CookieSpec;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecFactory;
+import ch.boye.httpclientandroidlib.cookie.CookieSpecProvider;
+import ch.boye.httpclientandroidlib.cookie.params.CookieSpecPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpContext;
+
+/**
+ * {@link CookieSpecProvider} implementation that creates and initializes
+ * {@link RFC2965Spec} instances.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class RFC2965SpecFactory implements CookieSpecFactory, CookieSpecProvider {
+
+ private final String[] datepatterns;
+ private final boolean oneHeader;
+
+ public RFC2965SpecFactory(final String[] datepatterns, final boolean oneHeader) {
+ super();
+ this.datepatterns = datepatterns;
+ this.oneHeader = oneHeader;
+ }
+
+ public RFC2965SpecFactory() {
+ this(null, false);
+ }
+
+ public CookieSpec newInstance(final HttpParams params) {
+ if (params != null) {
+
+ String[] patterns = null;
+ final Collection<?> param = (Collection<?>) params.getParameter(
+ CookieSpecPNames.DATE_PATTERNS);
+ if (param != null) {
+ patterns = new String[param.size()];
+ patterns = param.toArray(patterns);
+ }
+ final boolean singleHeader = params.getBooleanParameter(
+ CookieSpecPNames.SINGLE_COOKIE_HEADER, false);
+
+ return new RFC2965Spec(patterns, singleHeader);
+ } else {
+ return new RFC2965Spec();
+ }
+ }
+
+ public CookieSpec create(final HttpContext context) {
+ return new RFC2965Spec(this.datepatterns, this.oneHeader);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java
new file mode 100644
index 000000000..26ae4faa6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java
@@ -0,0 +1,94 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.cookie;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.cookie.ClientCookie;
+import ch.boye.httpclientandroidlib.cookie.Cookie;
+import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
+import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
+import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
+import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
+import ch.boye.httpclientandroidlib.cookie.SetCookie;
+import ch.boye.httpclientandroidlib.cookie.SetCookie2;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * <tt>"Version"</tt> cookie attribute handler for RFC 2965 cookie spec.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RFC2965VersionAttributeHandler implements CookieAttributeHandler {
+
+ public RFC2965VersionAttributeHandler() {
+ super();
+ }
+
+ /**
+ * Parse cookie version attribute.
+ */
+ public void parse(final SetCookie cookie, final String value)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (value == null) {
+ throw new MalformedCookieException(
+ "Missing value for version attribute");
+ }
+ int version = -1;
+ try {
+ version = Integer.parseInt(value);
+ } catch (final NumberFormatException e) {
+ version = -1;
+ }
+ if (version < 0) {
+ throw new MalformedCookieException("Invalid cookie version.");
+ }
+ cookie.setVersion(version);
+ }
+
+ /**
+ * validate cookie version attribute. Version attribute is REQUIRED.
+ */
+ public void validate(final Cookie cookie, final CookieOrigin origin)
+ throws MalformedCookieException {
+ Args.notNull(cookie, "Cookie");
+ if (cookie instanceof SetCookie2) {
+ if (cookie instanceof ClientCookie
+ && !((ClientCookie) cookie).containsAttribute(ClientCookie.VERSION_ATTR)) {
+ throw new CookieRestrictionViolationException(
+ "Violates RFC 2965. Version attribute is required.");
+ }
+ }
+ }
+
+ public boolean match(final Cookie cookie, final CookieOrigin origin) {
+ return true;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/package-info.java
new file mode 100644
index 000000000..1950e7263
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default implementations of standard and common HTTP state
+ * management policies.
+ */
+package ch.boye.httpclientandroidlib.impl.cookie;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/DisallowIdentityContentLengthStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/DisallowIdentityContentLengthStrategy.java
new file mode 100644
index 000000000..93556d22b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/DisallowIdentityContentLengthStrategy.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.entity;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+
+/**
+ * Decorator for {@link ContentLengthStrategy} implementations that disallows the use of
+ * identity transfer encoding.
+ *
+ * @since 4.2
+ */
+@Immutable
+public class DisallowIdentityContentLengthStrategy implements ContentLengthStrategy {
+
+ public static final DisallowIdentityContentLengthStrategy INSTANCE =
+ new DisallowIdentityContentLengthStrategy(new LaxContentLengthStrategy(0));
+
+ private final ContentLengthStrategy contentLengthStrategy;
+
+ public DisallowIdentityContentLengthStrategy(final ContentLengthStrategy contentLengthStrategy) {
+ super();
+ this.contentLengthStrategy = contentLengthStrategy;
+ }
+
+ public long determineLength(final HttpMessage message) throws HttpException {
+ final long result = this.contentLengthStrategy.determineLength(message);
+ if (result == ContentLengthStrategy.IDENTITY) {
+ throw new ProtocolException("Identity transfer encoding cannot be used");
+ }
+ return result;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntityDeserializer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntityDeserializer.java
new file mode 100644
index 000000000..5eba3638c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntityDeserializer.java
@@ -0,0 +1,143 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.entity;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.entity.BasicHttpEntity;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.io.ChunkedInputStream;
+import ch.boye.httpclientandroidlib.impl.io.ContentLengthInputStream;
+import ch.boye.httpclientandroidlib.impl.io.IdentityInputStream;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * HTTP entity deserializer.
+ * <p>
+ * This entity deserializer supports "chunked" and "identitiy" transfer-coding
+ * and content length delimited content.
+ * <p>
+ * This class relies on a specific implementation of
+ * {@link ContentLengthStrategy} to determine the content length or transfer
+ * encoding of the entity.
+ * <p>
+ * This class generates an instance of {@link HttpEntity} based on
+ * properties of the message. The content of the entity will be decoded
+ * transparently for the consumer.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.impl.BHttpConnectionBase}
+ */
+@Immutable // assuming injected dependencies are immutable
+@Deprecated
+public class EntityDeserializer {
+
+ private final ContentLengthStrategy lenStrategy;
+
+ public EntityDeserializer(final ContentLengthStrategy lenStrategy) {
+ super();
+ this.lenStrategy = Args.notNull(lenStrategy, "Content length strategy");
+ }
+
+ /**
+ * Creates a {@link BasicHttpEntity} based on properties of the given
+ * message. The content of the entity is created by wrapping
+ * {@link SessionInputBuffer} with a content decoder depending on the
+ * transfer mechanism used by the message.
+ * <p>
+ * This method is called by the public
+ * {@link #deserialize(SessionInputBuffer, HttpMessage)}.
+ *
+ * @param inbuffer the session input buffer.
+ * @param message the message.
+ * @return HTTP entity.
+ * @throws HttpException in case of HTTP protocol violation.
+ * @throws IOException in case of an I/O error.
+ */
+ protected BasicHttpEntity doDeserialize(
+ final SessionInputBuffer inbuffer,
+ final HttpMessage message) throws HttpException, IOException {
+ final BasicHttpEntity entity = new BasicHttpEntity();
+
+ final long len = this.lenStrategy.determineLength(message);
+ if (len == ContentLengthStrategy.CHUNKED) {
+ entity.setChunked(true);
+ entity.setContentLength(-1);
+ entity.setContent(new ChunkedInputStream(inbuffer));
+ } else if (len == ContentLengthStrategy.IDENTITY) {
+ entity.setChunked(false);
+ entity.setContentLength(-1);
+ entity.setContent(new IdentityInputStream(inbuffer));
+ } else {
+ entity.setChunked(false);
+ entity.setContentLength(len);
+ entity.setContent(new ContentLengthInputStream(inbuffer, len));
+ }
+
+ final Header contentTypeHeader = message.getFirstHeader(HTTP.CONTENT_TYPE);
+ if (contentTypeHeader != null) {
+ entity.setContentType(contentTypeHeader);
+ }
+ final Header contentEncodingHeader = message.getFirstHeader(HTTP.CONTENT_ENCODING);
+ if (contentEncodingHeader != null) {
+ entity.setContentEncoding(contentEncodingHeader);
+ }
+ return entity;
+ }
+
+ /**
+ * Creates an {@link HttpEntity} based on properties of the given message.
+ * The content of the entity is created by wrapping
+ * {@link SessionInputBuffer} with a content decoder depending on the
+ * transfer mechanism used by the message.
+ * <p>
+ * The content of the entity is NOT retrieved by this method.
+ *
+ * @param inbuffer the session input buffer.
+ * @param message the message.
+ * @return HTTP entity.
+ * @throws HttpException in case of HTTP protocol violation.
+ * @throws IOException in case of an I/O error.
+ */
+ public HttpEntity deserialize(
+ final SessionInputBuffer inbuffer,
+ final HttpMessage message) throws HttpException, IOException {
+ Args.notNull(inbuffer, "Session input buffer");
+ Args.notNull(message, "HTTP message");
+ return doDeserialize(inbuffer, message);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntitySerializer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntitySerializer.java
new file mode 100644
index 000000000..f25115cef
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/EntitySerializer.java
@@ -0,0 +1,121 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.entity;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.impl.io.ChunkedOutputStream;
+import ch.boye.httpclientandroidlib.impl.io.ContentLengthOutputStream;
+import ch.boye.httpclientandroidlib.impl.io.IdentityOutputStream;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * HTTP entity serializer.
+ * <p>
+ * This entity serializer currently supports "chunked" and "identitiy"
+ * transfer-coding and content length delimited content.
+ * <p>
+ * This class relies on a specific implementation of
+ * {@link ContentLengthStrategy} to determine the content length or transfer
+ * encoding of the entity.
+ * <p>
+ * This class writes out the content of {@link HttpEntity} to the data stream
+ * using a transfer coding based on properties on the HTTP message.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.impl.BHttpConnectionBase}
+ */
+@Immutable // assuming injected dependencies are immutable
+@Deprecated
+public class EntitySerializer {
+
+ private final ContentLengthStrategy lenStrategy;
+
+ public EntitySerializer(final ContentLengthStrategy lenStrategy) {
+ super();
+ this.lenStrategy = Args.notNull(lenStrategy, "Content length strategy");
+ }
+
+ /**
+ * Creates a transfer codec based on properties of the given HTTP message
+ * and returns {@link OutputStream} instance that transparently encodes
+ * output data as it is being written out to the output stream.
+ * <p>
+ * This method is called by the public
+ * {@link #serialize(SessionOutputBuffer, HttpMessage, HttpEntity)}.
+ *
+ * @param outbuffer the session output buffer.
+ * @param message the HTTP message.
+ * @return output stream.
+ * @throws HttpException in case of HTTP protocol violation.
+ * @throws IOException in case of an I/O error.
+ */
+ protected OutputStream doSerialize(
+ final SessionOutputBuffer outbuffer,
+ final HttpMessage message) throws HttpException, IOException {
+ final long len = this.lenStrategy.determineLength(message);
+ if (len == ContentLengthStrategy.CHUNKED) {
+ return new ChunkedOutputStream(outbuffer);
+ } else if (len == ContentLengthStrategy.IDENTITY) {
+ return new IdentityOutputStream(outbuffer);
+ } else {
+ return new ContentLengthOutputStream(outbuffer, len);
+ }
+ }
+
+ /**
+ * Writes out the content of the given HTTP entity to the session output
+ * buffer based on properties of the given HTTP message.
+ *
+ * @param outbuffer the output session buffer.
+ * @param message the HTTP message.
+ * @param entity the HTTP entity to be written out.
+ * @throws HttpException in case of HTTP protocol violation.
+ * @throws IOException in case of an I/O error.
+ */
+ public void serialize(
+ final SessionOutputBuffer outbuffer,
+ final HttpMessage message,
+ final HttpEntity entity) throws HttpException, IOException {
+ Args.notNull(outbuffer, "Session output buffer");
+ Args.notNull(message, "HTTP message");
+ Args.notNull(entity, "HTTP entity");
+ final OutputStream outstream = doSerialize(outbuffer, message);
+ entity.writeTo(outstream);
+ outstream.close();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java
new file mode 100644
index 000000000..0f0dbaf15
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java
@@ -0,0 +1,126 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.entity;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * The lax implementation of the content length strategy. This class will ignore
+ * unrecognized transfer encodings and malformed <code>Content-Length</code>
+ * header values.
+ * <p/>
+ * This class recognizes "chunked" and "identitiy" transfer-coding only.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class LaxContentLengthStrategy implements ContentLengthStrategy {
+
+ public static final LaxContentLengthStrategy INSTANCE = new LaxContentLengthStrategy();
+
+ private final int implicitLen;
+
+ /**
+ * Creates <tt>LaxContentLengthStrategy</tt> instance with the given length used per default
+ * when content length is not explicitly specified in the message.
+ *
+ * @param implicitLen implicit content length.
+ *
+ * @since 4.2
+ */
+ public LaxContentLengthStrategy(final int implicitLen) {
+ super();
+ this.implicitLen = implicitLen;
+ }
+
+ /**
+ * Creates <tt>LaxContentLengthStrategy</tt> instance. {@link ContentLengthStrategy#IDENTITY}
+ * is used per default when content length is not explicitly specified in the message.
+ */
+ public LaxContentLengthStrategy() {
+ this(IDENTITY);
+ }
+
+ public long determineLength(final HttpMessage message) throws HttpException {
+ Args.notNull(message, "HTTP message");
+
+ final Header transferEncodingHeader = message.getFirstHeader(HTTP.TRANSFER_ENCODING);
+ // We use Transfer-Encoding if present and ignore Content-Length.
+ // RFC2616, 4.4 item number 3
+ if (transferEncodingHeader != null) {
+ final HeaderElement[] encodings;
+ try {
+ encodings = transferEncodingHeader.getElements();
+ } catch (final ParseException px) {
+ throw new ProtocolException
+ ("Invalid Transfer-Encoding header value: " +
+ transferEncodingHeader, px);
+ }
+ // The chunked encoding must be the last one applied RFC2616, 14.41
+ final int len = encodings.length;
+ if (HTTP.IDENTITY_CODING.equalsIgnoreCase(transferEncodingHeader.getValue())) {
+ return IDENTITY;
+ } else if ((len > 0) && (HTTP.CHUNK_CODING.equalsIgnoreCase(
+ encodings[len - 1].getName()))) {
+ return CHUNKED;
+ } else {
+ return IDENTITY;
+ }
+ }
+ final Header contentLengthHeader = message.getFirstHeader(HTTP.CONTENT_LEN);
+ if (contentLengthHeader != null) {
+ long contentlen = -1;
+ final Header[] headers = message.getHeaders(HTTP.CONTENT_LEN);
+ for (int i = headers.length - 1; i >= 0; i--) {
+ final Header header = headers[i];
+ try {
+ contentlen = Long.parseLong(header.getValue());
+ break;
+ } catch (final NumberFormatException ignore) {
+ }
+ // See if we can have better luck with another header, if present
+ }
+ if (contentlen >= 0) {
+ return contentlen;
+ } else {
+ return IDENTITY;
+ }
+ }
+ return this.implicitLen;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java
new file mode 100644
index 000000000..1693c3111
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java
@@ -0,0 +1,116 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.entity;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.entity.ContentLengthStrategy;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * The strict implementation of the content length strategy. This class
+ * will throw {@link ProtocolException} if it encounters an unsupported
+ * transfer encoding or a malformed <code>Content-Length</code> header
+ * value.
+ * <p>
+ * This class recognizes "chunked" and "identitiy" transfer-coding only.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class StrictContentLengthStrategy implements ContentLengthStrategy {
+
+ public static final StrictContentLengthStrategy INSTANCE = new StrictContentLengthStrategy();
+
+ private final int implicitLen;
+
+ /**
+ * Creates <tt>StrictContentLengthStrategy</tt> instance with the given length used per default
+ * when content length is not explicitly specified in the message.
+ *
+ * @param implicitLen implicit content length.
+ *
+ * @since 4.2
+ */
+ public StrictContentLengthStrategy(final int implicitLen) {
+ super();
+ this.implicitLen = implicitLen;
+ }
+
+ /**
+ * Creates <tt>StrictContentLengthStrategy</tt> instance. {@link ContentLengthStrategy#IDENTITY}
+ * is used per default when content length is not explicitly specified in the message.
+ */
+ public StrictContentLengthStrategy() {
+ this(IDENTITY);
+ }
+
+ public long determineLength(final HttpMessage message) throws HttpException {
+ Args.notNull(message, "HTTP message");
+ // Although Transfer-Encoding is specified as a list, in practice
+ // it is either missing or has the single value "chunked". So we
+ // treat it as a single-valued header here.
+ final Header transferEncodingHeader = message.getFirstHeader(HTTP.TRANSFER_ENCODING);
+ if (transferEncodingHeader != null) {
+ final String s = transferEncodingHeader.getValue();
+ if (HTTP.CHUNK_CODING.equalsIgnoreCase(s)) {
+ if (message.getProtocolVersion().lessEquals(HttpVersion.HTTP_1_0)) {
+ throw new ProtocolException(
+ "Chunked transfer encoding not allowed for " +
+ message.getProtocolVersion());
+ }
+ return CHUNKED;
+ } else if (HTTP.IDENTITY_CODING.equalsIgnoreCase(s)) {
+ return IDENTITY;
+ } else {
+ throw new ProtocolException(
+ "Unsupported transfer encoding: " + s);
+ }
+ }
+ final Header contentLengthHeader = message.getFirstHeader(HTTP.CONTENT_LEN);
+ if (contentLengthHeader != null) {
+ final String s = contentLengthHeader.getValue();
+ try {
+ final long len = Long.parseLong(s);
+ if (len < 0) {
+ throw new ProtocolException("Negative content length: " + s);
+ }
+ return len;
+ } catch (final NumberFormatException e) {
+ throw new ProtocolException("Invalid content length: " + s);
+ }
+ }
+ return this.implicitLen;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/package-info.java
new file mode 100644
index 000000000..7566c4570
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/entity/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default implementations of entity content strategies.
+ */
+package ch.boye.httpclientandroidlib.impl.entity;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/BackoffStrategyExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/BackoffStrategyExec.java
new file mode 100644
index 000000000..a639da934
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/BackoffStrategyExec.java
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.BackoffManager;
+import ch.boye.httpclientandroidlib.client.ConnectionBackoffStrategy;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * @since 4.3
+ */
+@Immutable
+public class BackoffStrategyExec implements ClientExecChain {
+
+ private final ClientExecChain requestExecutor;
+ private final ConnectionBackoffStrategy connectionBackoffStrategy;
+ private final BackoffManager backoffManager;
+
+ public BackoffStrategyExec(
+ final ClientExecChain requestExecutor,
+ final ConnectionBackoffStrategy connectionBackoffStrategy,
+ final BackoffManager backoffManager) {
+ super();
+ Args.notNull(requestExecutor, "HTTP client request executor");
+ Args.notNull(connectionBackoffStrategy, "Connection backoff strategy");
+ Args.notNull(backoffManager, "Backoff manager");
+ this.requestExecutor = requestExecutor;
+ this.connectionBackoffStrategy = connectionBackoffStrategy;
+ this.backoffManager = backoffManager;
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+ Args.notNull(route, "HTTP route");
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+ CloseableHttpResponse out = null;
+ try {
+ out = this.requestExecutor.execute(route, request, context, execAware);
+ } catch (final Exception ex) {
+ if (out != null) {
+ out.close();
+ }
+ if (this.connectionBackoffStrategy.shouldBackoff(ex)) {
+ this.backoffManager.backOff(route);
+ }
+ if (ex instanceof RuntimeException) {
+ throw (RuntimeException) ex;
+ }
+ if (ex instanceof HttpException) {
+ throw (HttpException) ex;
+ }
+ if (ex instanceof IOException) {
+ throw (IOException) ex;
+ }
+ throw new UndeclaredThrowableException(ex);
+ }
+ if (this.connectionBackoffStrategy.shouldBackoff(out)) {
+ this.backoffManager.backOff(route);
+ } else {
+ this.backoffManager.probe(route);
+ }
+ return out;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ClientExecChain.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ClientExecChain.java
new file mode 100644
index 000000000..2b5e3c8f6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ClientExecChain.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+
+/**
+ * This interface represents an element in the HTTP request execution chain. Each element can
+ * either be a decorator around another element that implements a cross cutting aspect or
+ * a self-contained executor capable of producing a response for the given request.
+ * <p/>
+ * Important: please note it is required for decorators that implement post execution aspects
+ * or response post-processing of any sort to release resources associated with the response
+ * by calling {@link CloseableHttpResponse#close()} methods in case of an I/O, protocol or
+ * runtime exception, or in case the response is not propagated to the caller.
+ *
+ * @since 4.3
+ */
+public interface ClientExecChain {
+
+ /**
+ * Executes th request either by transmitting it to the target server or
+ * by passing it onto the next executor in the request execution chain.
+ *
+ * @param route connection route.
+ * @param request current request.
+ * @param clientContext current HTTP context.
+ * @param execAware receiver of notifications of blocking I/O operations.
+ * @return HTTP response either received from the opposite endpoint
+ * or generated locally.
+ * @throws IOException in case of a I/O error.
+ * (this type of exceptions are potentially recoverable).
+ * @throws HttpException in case of an HTTP protocol error
+ * (usually this type of exceptions are non-recoverable).
+ */
+ CloseableHttpResponse execute(
+ HttpRoute route,
+ HttpRequestWrapper request,
+ HttpClientContext clientContext,
+ HttpExecutionAware execAware) throws IOException, HttpException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ConnectionHolder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ConnectionHolder.java
new file mode 100644
index 000000000..d9bb17286
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ConnectionHolder.java
@@ -0,0 +1,153 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.concurrent.Cancellable;
+import ch.boye.httpclientandroidlib.conn.ConnectionReleaseTrigger;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+
+/**
+ * Internal connection holder.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+class ConnectionHolder implements ConnectionReleaseTrigger, Cancellable, Closeable {
+
+ public HttpClientAndroidLog log;
+
+ private final HttpClientConnectionManager manager;
+ private final HttpClientConnection managedConn;
+ private volatile boolean reusable;
+ private volatile Object state;
+ private volatile long validDuration;
+ private volatile TimeUnit tunit;
+
+ private volatile boolean released;
+
+ public ConnectionHolder(
+ final HttpClientAndroidLog log,
+ final HttpClientConnectionManager manager,
+ final HttpClientConnection managedConn) {
+ super();
+ this.log = log;
+ this.manager = manager;
+ this.managedConn = managedConn;
+ }
+
+ public boolean isReusable() {
+ return this.reusable;
+ }
+
+ public void markReusable() {
+ this.reusable = true;
+ }
+
+ public void markNonReusable() {
+ this.reusable = false;
+ }
+
+ public void setState(final Object state) {
+ this.state = state;
+ }
+
+ public void setValidFor(final long duration, final TimeUnit tunit) {
+ synchronized (this.managedConn) {
+ this.validDuration = duration;
+ this.tunit = tunit;
+ }
+ }
+
+ public void releaseConnection() {
+ synchronized (this.managedConn) {
+ if (this.released) {
+ return;
+ }
+ this.released = true;
+ if (this.reusable) {
+ this.manager.releaseConnection(this.managedConn,
+ this.state, this.validDuration, this.tunit);
+ } else {
+ try {
+ this.managedConn.close();
+ log.debug("Connection discarded");
+ } catch (final IOException ex) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage(), ex);
+ }
+ } finally {
+ this.manager.releaseConnection(
+ this.managedConn, null, 0, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+ }
+
+ public void abortConnection() {
+ synchronized (this.managedConn) {
+ if (this.released) {
+ return;
+ }
+ this.released = true;
+ try {
+ this.managedConn.shutdown();
+ log.debug("Connection discarded");
+ } catch (final IOException ex) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage(), ex);
+ }
+ } finally {
+ this.manager.releaseConnection(
+ this.managedConn, null, 0, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+
+ public boolean cancel() {
+ final boolean alreadyReleased = this.released;
+ log.debug("Cancelling request execution");
+ abortConnection();
+ return !alreadyReleased;
+ }
+
+ public boolean isReleased() {
+ return this.released;
+ }
+
+ public void close() throws IOException {
+ abortConnection();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/HttpResponseProxy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/HttpResponseProxy.java
new file mode 100644
index 000000000..1fdc027c8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/HttpResponseProxy.java
@@ -0,0 +1,185 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * A proxy class for {@link ch.boye.httpclientandroidlib.HttpResponse} that can be used to release client connection
+ * associated with the original response.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+class HttpResponseProxy implements CloseableHttpResponse {
+
+ private final HttpResponse original;
+ private final ConnectionHolder connHolder;
+
+ public HttpResponseProxy(final HttpResponse original, final ConnectionHolder connHolder) {
+ this.original = original;
+ this.connHolder = connHolder;
+ ResponseEntityProxy.enchance(original, connHolder);
+ }
+
+ public void close() throws IOException {
+ if (this.connHolder != null) {
+ this.connHolder.abortConnection();
+ }
+ }
+
+ public StatusLine getStatusLine() {
+ return original.getStatusLine();
+ }
+
+ public void setStatusLine(final StatusLine statusline) {
+ original.setStatusLine(statusline);
+ }
+
+ public void setStatusLine(final ProtocolVersion ver, final int code) {
+ original.setStatusLine(ver, code);
+ }
+
+ public void setStatusLine(final ProtocolVersion ver, final int code, final String reason) {
+ original.setStatusLine(ver, code, reason);
+ }
+
+ public void setStatusCode(final int code) throws IllegalStateException {
+ original.setStatusCode(code);
+ }
+
+ public void setReasonPhrase(final String reason) throws IllegalStateException {
+ original.setReasonPhrase(reason);
+ }
+
+ public HttpEntity getEntity() {
+ return original.getEntity();
+ }
+
+ public void setEntity(final HttpEntity entity) {
+ original.setEntity(entity);
+ }
+
+ public Locale getLocale() {
+ return original.getLocale();
+ }
+
+ public void setLocale(final Locale loc) {
+ original.setLocale(loc);
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ return original.getProtocolVersion();
+ }
+
+ public boolean containsHeader(final String name) {
+ return original.containsHeader(name);
+ }
+
+ public Header[] getHeaders(final String name) {
+ return original.getHeaders(name);
+ }
+
+ public Header getFirstHeader(final String name) {
+ return original.getFirstHeader(name);
+ }
+
+ public Header getLastHeader(final String name) {
+ return original.getLastHeader(name);
+ }
+
+ public Header[] getAllHeaders() {
+ return original.getAllHeaders();
+ }
+
+ public void addHeader(final Header header) {
+ original.addHeader(header);
+ }
+
+ public void addHeader(final String name, final String value) {
+ original.addHeader(name, value);
+ }
+
+ public void setHeader(final Header header) {
+ original.setHeader(header);
+ }
+
+ public void setHeader(final String name, final String value) {
+ original.setHeader(name, value);
+ }
+
+ public void setHeaders(final Header[] headers) {
+ original.setHeaders(headers);
+ }
+
+ public void removeHeader(final Header header) {
+ original.removeHeader(header);
+ }
+
+ public void removeHeaders(final String name) {
+ original.removeHeaders(name);
+ }
+
+ public HeaderIterator headerIterator() {
+ return original.headerIterator();
+ }
+
+ public HeaderIterator headerIterator(final String name) {
+ return original.headerIterator(name);
+ }
+
+ @Deprecated
+ public HttpParams getParams() {
+ return original.getParams();
+ }
+
+ @Deprecated
+ public void setParams(final HttpParams params) {
+ original.setParams(params);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("HttpResponseProxy{");
+ sb.append(original);
+ sb.append('}');
+ return sb.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MainClientExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MainClientExec.java
new file mode 100644
index 000000000..cf1dbfde4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MainClientExec.java
@@ -0,0 +1,568 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AUTH;
+import ch.boye.httpclientandroidlib.auth.AuthProtocolState;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.client.AuthenticationStrategy;
+import ch.boye.httpclientandroidlib.client.NonRepeatableRequestException;
+import ch.boye.httpclientandroidlib.client.UserTokenHandler;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.client.protocol.RequestClientConnControl;
+import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy;
+import ch.boye.httpclientandroidlib.conn.ConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.routing.BasicRouteDirector;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRouteDirector;
+import ch.boye.httpclientandroidlib.conn.routing.RouteTracker;
+import ch.boye.httpclientandroidlib.entity.BufferedHttpEntity;
+import ch.boye.httpclientandroidlib.impl.auth.HttpAuthenticator;
+import ch.boye.httpclientandroidlib.impl.conn.ConnectionShutdownException;
+import ch.boye.httpclientandroidlib.message.BasicHttpRequest;
+import ch.boye.httpclientandroidlib.protocol.HttpCoreContext;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor;
+import ch.boye.httpclientandroidlib.protocol.ImmutableHttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.RequestTargetHost;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * The last request executor in the HTTP request execution chain
+ * that is responsible for execution of request / response
+ * exchanges with the opposite endpoint.
+ * This executor will automatically retry the request in case
+ * of an authentication challenge by an intermediate proxy or
+ * by the target server.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class MainClientExec implements ClientExecChain {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final HttpRequestExecutor requestExecutor;
+ private final HttpClientConnectionManager connManager;
+ private final ConnectionReuseStrategy reuseStrategy;
+ private final ConnectionKeepAliveStrategy keepAliveStrategy;
+ private final HttpProcessor proxyHttpProcessor;
+ private final AuthenticationStrategy targetAuthStrategy;
+ private final AuthenticationStrategy proxyAuthStrategy;
+ private final HttpAuthenticator authenticator;
+ private final UserTokenHandler userTokenHandler;
+ private final HttpRouteDirector routeDirector;
+
+
+ public MainClientExec(
+ final HttpRequestExecutor requestExecutor,
+ final HttpClientConnectionManager connManager,
+ final ConnectionReuseStrategy reuseStrategy,
+ final ConnectionKeepAliveStrategy keepAliveStrategy,
+ final AuthenticationStrategy targetAuthStrategy,
+ final AuthenticationStrategy proxyAuthStrategy,
+ final UserTokenHandler userTokenHandler) {
+ Args.notNull(requestExecutor, "HTTP request executor");
+ Args.notNull(connManager, "Client connection manager");
+ Args.notNull(reuseStrategy, "Connection reuse strategy");
+ Args.notNull(keepAliveStrategy, "Connection keep alive strategy");
+ Args.notNull(targetAuthStrategy, "Target authentication strategy");
+ Args.notNull(proxyAuthStrategy, "Proxy authentication strategy");
+ Args.notNull(userTokenHandler, "User token handler");
+ this.authenticator = new HttpAuthenticator();
+ this.proxyHttpProcessor = new ImmutableHttpProcessor(
+ new RequestTargetHost(), new RequestClientConnControl());
+ this.routeDirector = new BasicRouteDirector();
+ this.requestExecutor = requestExecutor;
+ this.connManager = connManager;
+ this.reuseStrategy = reuseStrategy;
+ this.keepAliveStrategy = keepAliveStrategy;
+ this.targetAuthStrategy = targetAuthStrategy;
+ this.proxyAuthStrategy = proxyAuthStrategy;
+ this.userTokenHandler = userTokenHandler;
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+ Args.notNull(route, "HTTP route");
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ AuthState targetAuthState = context.getTargetAuthState();
+ if (targetAuthState == null) {
+ targetAuthState = new AuthState();
+ context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, targetAuthState);
+ }
+ AuthState proxyAuthState = context.getProxyAuthState();
+ if (proxyAuthState == null) {
+ proxyAuthState = new AuthState();
+ context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
+ }
+
+ if (request instanceof HttpEntityEnclosingRequest) {
+ RequestEntityProxy.enhance((HttpEntityEnclosingRequest) request);
+ }
+
+ Object userToken = context.getUserToken();
+
+ final ConnectionRequest connRequest = connManager.requestConnection(route, userToken);
+ if (execAware != null) {
+ if (execAware.isAborted()) {
+ connRequest.cancel();
+ throw new RequestAbortedException("Request aborted");
+ } else {
+ execAware.setCancellable(connRequest);
+ }
+ }
+
+ final RequestConfig config = context.getRequestConfig();
+
+ final HttpClientConnection managedConn;
+ try {
+ final int timeout = config.getConnectionRequestTimeout();
+ managedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS);
+ } catch(final InterruptedException interrupted) {
+ Thread.currentThread().interrupt();
+ throw new RequestAbortedException("Request aborted", interrupted);
+ } catch(final ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ if (cause == null) {
+ cause = ex;
+ }
+ throw new RequestAbortedException("Request execution failed", cause);
+ }
+
+ context.setAttribute(HttpCoreContext.HTTP_CONNECTION, managedConn);
+
+ if (config.isStaleConnectionCheckEnabled()) {
+ // validate connection
+ if (managedConn.isOpen()) {
+ this.log.debug("Stale connection check");
+ if (managedConn.isStale()) {
+ this.log.debug("Stale connection detected");
+ managedConn.close();
+ }
+ }
+ }
+
+ final ConnectionHolder connHolder = new ConnectionHolder(this.log, this.connManager, managedConn);
+ try {
+ if (execAware != null) {
+ execAware.setCancellable(connHolder);
+ }
+
+ HttpResponse response;
+ for (int execCount = 1;; execCount++) {
+
+ if (execCount > 1 && !RequestEntityProxy.isRepeatable(request)) {
+ throw new NonRepeatableRequestException("Cannot retry request " +
+ "with a non-repeatable request entity.");
+ }
+
+ if (execAware != null && execAware.isAborted()) {
+ throw new RequestAbortedException("Request aborted");
+ }
+
+ if (!managedConn.isOpen()) {
+ this.log.debug("Opening connection " + route);
+ try {
+ establishRoute(proxyAuthState, managedConn, route, request, context);
+ } catch (final TunnelRefusedException ex) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage());
+ }
+ response = ex.getResponse();
+ break;
+ }
+ }
+ final int timeout = config.getSocketTimeout();
+ if (timeout >= 0) {
+ managedConn.setSocketTimeout(timeout);
+ }
+
+ if (execAware != null && execAware.isAborted()) {
+ throw new RequestAbortedException("Request aborted");
+ }
+
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Executing request " + request.getRequestLine());
+ }
+
+ if (!request.containsHeader(AUTH.WWW_AUTH_RESP)) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Target auth state: " + targetAuthState.getState());
+ }
+ this.authenticator.generateAuthResponse(request, targetAuthState, context);
+ }
+ if (!request.containsHeader(AUTH.PROXY_AUTH_RESP) && !route.isTunnelled()) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Proxy auth state: " + proxyAuthState.getState());
+ }
+ this.authenticator.generateAuthResponse(request, proxyAuthState, context);
+ }
+
+ response = requestExecutor.execute(request, managedConn, context);
+
+ // The connection is in or can be brought to a re-usable state.
+ if (reuseStrategy.keepAlive(response, context)) {
+ // Set the idle duration of this connection
+ final long duration = keepAliveStrategy.getKeepAliveDuration(response, context);
+ if (this.log.isDebugEnabled()) {
+ final String s;
+ if (duration > 0) {
+ s = "for " + duration + " " + TimeUnit.MILLISECONDS;
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection can be kept alive " + s);
+ }
+ connHolder.setValidFor(duration, TimeUnit.MILLISECONDS);
+ connHolder.markReusable();
+ } else {
+ connHolder.markNonReusable();
+ }
+
+ if (needAuthentication(
+ targetAuthState, proxyAuthState, route, response, context)) {
+ // Make sure the response body is fully consumed, if present
+ final HttpEntity entity = response.getEntity();
+ if (connHolder.isReusable()) {
+ EntityUtils.consume(entity);
+ } else {
+ managedConn.close();
+ if (proxyAuthState.getState() == AuthProtocolState.SUCCESS
+ && proxyAuthState.getAuthScheme() != null
+ && proxyAuthState.getAuthScheme().isConnectionBased()) {
+ this.log.debug("Resetting proxy auth state");
+ proxyAuthState.reset();
+ }
+ if (targetAuthState.getState() == AuthProtocolState.SUCCESS
+ && targetAuthState.getAuthScheme() != null
+ && targetAuthState.getAuthScheme().isConnectionBased()) {
+ this.log.debug("Resetting target auth state");
+ targetAuthState.reset();
+ }
+ }
+ // discard previous auth headers
+ final HttpRequest original = request.getOriginal();
+ if (!original.containsHeader(AUTH.WWW_AUTH_RESP)) {
+ request.removeHeaders(AUTH.WWW_AUTH_RESP);
+ }
+ if (!original.containsHeader(AUTH.PROXY_AUTH_RESP)) {
+ request.removeHeaders(AUTH.PROXY_AUTH_RESP);
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (userToken == null) {
+ userToken = userTokenHandler.getUserToken(context);
+ context.setAttribute(HttpClientContext.USER_TOKEN, userToken);
+ }
+ if (userToken != null) {
+ connHolder.setState(userToken);
+ }
+
+ // check for entity, release connection if possible
+ final HttpEntity entity = response.getEntity();
+ if (entity == null || !entity.isStreaming()) {
+ // connection not needed and (assumed to be) in re-usable state
+ connHolder.releaseConnection();
+ return new HttpResponseProxy(response, null);
+ } else {
+ return new HttpResponseProxy(response, connHolder);
+ }
+ } catch (final ConnectionShutdownException ex) {
+ final InterruptedIOException ioex = new InterruptedIOException(
+ "Connection has been shut down");
+ ioex.initCause(ex);
+ throw ioex;
+ } catch (final HttpException ex) {
+ connHolder.abortConnection();
+ throw ex;
+ } catch (final IOException ex) {
+ connHolder.abortConnection();
+ throw ex;
+ } catch (final RuntimeException ex) {
+ connHolder.abortConnection();
+ throw ex;
+ }
+ }
+
+ /**
+ * Establishes the target route.
+ */
+ void establishRoute(
+ final AuthState proxyAuthState,
+ final HttpClientConnection managedConn,
+ final HttpRoute route,
+ final HttpRequest request,
+ final HttpClientContext context) throws HttpException, IOException {
+ final RequestConfig config = context.getRequestConfig();
+ final int timeout = config.getConnectTimeout();
+ final RouteTracker tracker = new RouteTracker(route);
+ int step;
+ do {
+ final HttpRoute fact = tracker.toRoute();
+ step = this.routeDirector.nextStep(route, fact);
+
+ switch (step) {
+
+ case HttpRouteDirector.CONNECT_TARGET:
+ this.connManager.connect(
+ managedConn,
+ route,
+ timeout > 0 ? timeout : 0,
+ context);
+ tracker.connectTarget(route.isSecure());
+ break;
+ case HttpRouteDirector.CONNECT_PROXY:
+ this.connManager.connect(
+ managedConn,
+ route,
+ timeout > 0 ? timeout : 0,
+ context);
+ final HttpHost proxy = route.getProxyHost();
+ tracker.connectProxy(proxy, false);
+ break;
+ case HttpRouteDirector.TUNNEL_TARGET: {
+ final boolean secure = createTunnelToTarget(
+ proxyAuthState, managedConn, route, request, context);
+ this.log.debug("Tunnel to target created.");
+ tracker.tunnelTarget(secure);
+ } break;
+
+ case HttpRouteDirector.TUNNEL_PROXY: {
+ // The most simple example for this case is a proxy chain
+ // of two proxies, where P1 must be tunnelled to P2.
+ // route: Source -> P1 -> P2 -> Target (3 hops)
+ // fact: Source -> P1 -> Target (2 hops)
+ final int hop = fact.getHopCount()-1; // the hop to establish
+ final boolean secure = createTunnelToProxy(route, hop, context);
+ this.log.debug("Tunnel to proxy created.");
+ tracker.tunnelProxy(route.getHopTarget(hop), secure);
+ } break;
+
+ case HttpRouteDirector.LAYER_PROTOCOL:
+ this.connManager.upgrade(managedConn, route, context);
+ tracker.layerProtocol(route.isSecure());
+ break;
+
+ case HttpRouteDirector.UNREACHABLE:
+ throw new HttpException("Unable to establish route: " +
+ "planned = " + route + "; current = " + fact);
+ case HttpRouteDirector.COMPLETE:
+ this.connManager.routeComplete(managedConn, route, context);
+ break;
+ default:
+ throw new IllegalStateException("Unknown step indicator "
+ + step + " from RouteDirector.");
+ }
+
+ } while (step > HttpRouteDirector.COMPLETE);
+ }
+
+ /**
+ * Creates a tunnel to the target server.
+ * The connection must be established to the (last) proxy.
+ * A CONNECT request for tunnelling through the proxy will
+ * be created and sent, the response received and checked.
+ * This method does <i>not</i> update the connection with
+ * information about the tunnel, that is left to the caller.
+ */
+ private boolean createTunnelToTarget(
+ final AuthState proxyAuthState,
+ final HttpClientConnection managedConn,
+ final HttpRoute route,
+ final HttpRequest request,
+ final HttpClientContext context) throws HttpException, IOException {
+
+ final RequestConfig config = context.getRequestConfig();
+ final int timeout = config.getConnectTimeout();
+
+ final HttpHost target = route.getTargetHost();
+ final HttpHost proxy = route.getProxyHost();
+ HttpResponse response = null;
+
+ final String authority = target.toHostString();
+ final HttpRequest connect = new BasicHttpRequest("CONNECT", authority, request.getProtocolVersion());
+
+ this.requestExecutor.preProcess(connect, this.proxyHttpProcessor, context);
+
+ while (response == null) {
+ if (!managedConn.isOpen()) {
+ this.connManager.connect(
+ managedConn,
+ route,
+ timeout > 0 ? timeout : 0,
+ context);
+ }
+
+ connect.removeHeaders(AUTH.PROXY_AUTH_RESP);
+ this.authenticator.generateAuthResponse(connect, proxyAuthState, context);
+
+ response = this.requestExecutor.execute(connect, managedConn, context);
+
+ final int status = response.getStatusLine().getStatusCode();
+ if (status < 200) {
+ throw new HttpException("Unexpected response to CONNECT request: " +
+ response.getStatusLine());
+ }
+
+ if (config.isAuthenticationEnabled()) {
+ if (this.authenticator.isAuthenticationRequested(proxy, response,
+ this.proxyAuthStrategy, proxyAuthState, context)) {
+ if (this.authenticator.handleAuthChallenge(proxy, response,
+ this.proxyAuthStrategy, proxyAuthState, context)) {
+ // Retry request
+ if (this.reuseStrategy.keepAlive(response, context)) {
+ this.log.debug("Connection kept alive");
+ // Consume response content
+ final HttpEntity entity = response.getEntity();
+ EntityUtils.consume(entity);
+ } else {
+ managedConn.close();
+ }
+ response = null;
+ }
+ }
+ }
+ }
+
+ final int status = response.getStatusLine().getStatusCode();
+
+ if (status > 299) {
+
+ // Buffer response content
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ response.setEntity(new BufferedHttpEntity(entity));
+ }
+
+ managedConn.close();
+ throw new TunnelRefusedException("CONNECT refused by proxy: " +
+ response.getStatusLine(), response);
+ }
+
+ // How to decide on security of the tunnelled connection?
+ // The socket factory knows only about the segment to the proxy.
+ // Even if that is secure, the hop to the target may be insecure.
+ // Leave it to derived classes, consider insecure by default here.
+ return false;
+ }
+
+ /**
+ * Creates a tunnel to an intermediate proxy.
+ * This method is <i>not</i> implemented in this class.
+ * It just throws an exception here.
+ */
+ private boolean createTunnelToProxy(
+ final HttpRoute route,
+ final int hop,
+ final HttpClientContext context) throws HttpException {
+
+ // Have a look at createTunnelToTarget and replicate the parts
+ // you need in a custom derived class. If your proxies don't require
+ // authentication, it is not too hard. But for the stock version of
+ // HttpClient, we cannot make such simplifying assumptions and would
+ // have to include proxy authentication code. The HttpComponents team
+ // is currently not in a position to support rarely used code of this
+ // complexity. Feel free to submit patches that refactor the code in
+ // createTunnelToTarget to facilitate re-use for proxy tunnelling.
+
+ throw new HttpException("Proxy chains are not supported.");
+ }
+
+ private boolean needAuthentication(
+ final AuthState targetAuthState,
+ final AuthState proxyAuthState,
+ final HttpRoute route,
+ final HttpResponse response,
+ final HttpClientContext context) {
+ final RequestConfig config = context.getRequestConfig();
+ if (config.isAuthenticationEnabled()) {
+ HttpHost target = context.getTargetHost();
+ if (target == null) {
+ target = route.getTargetHost();
+ }
+ if (target.getPort() < 0) {
+ target = new HttpHost(
+ target.getHostName(),
+ route.getTargetHost().getPort(),
+ target.getSchemeName());
+ }
+ final boolean targetAuthRequested = this.authenticator.isAuthenticationRequested(
+ target, response, this.targetAuthStrategy, targetAuthState, context);
+
+ HttpHost proxy = route.getProxyHost();
+ // if proxy is not set use target host instead
+ if (proxy == null) {
+ proxy = route.getTargetHost();
+ }
+ final boolean proxyAuthRequested = this.authenticator.isAuthenticationRequested(
+ proxy, response, this.proxyAuthStrategy, proxyAuthState, context);
+
+ if (targetAuthRequested) {
+ return this.authenticator.handleAuthChallenge(target, response,
+ this.targetAuthStrategy, targetAuthState, context);
+ }
+ if (proxyAuthRequested) {
+ return this.authenticator.handleAuthChallenge(proxy, response,
+ this.proxyAuthStrategy, proxyAuthState, context);
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MinimalClientExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MinimalClientExec.java
new file mode 100644
index 000000000..16f6176eb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/MinimalClientExec.java
@@ -0,0 +1,251 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.client.protocol.RequestClientConnControl;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.conn.ConnectionKeepAliveStrategy;
+import ch.boye.httpclientandroidlib.conn.ConnectionRequest;
+import ch.boye.httpclientandroidlib.conn.HttpClientConnectionManager;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.impl.conn.ConnectionShutdownException;
+import ch.boye.httpclientandroidlib.protocol.HttpCoreContext;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor;
+import ch.boye.httpclientandroidlib.protocol.ImmutableHttpProcessor;
+import ch.boye.httpclientandroidlib.protocol.RequestContent;
+import ch.boye.httpclientandroidlib.protocol.RequestTargetHost;
+import ch.boye.httpclientandroidlib.protocol.RequestUserAgent;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.VersionInfo;
+
+/**
+ * Request executor that implements the most fundamental aspects of
+ * the HTTP specification and the most straight-forward request / response
+ * exchange with the target server. This executor does not support
+ * execution via proxy and will make no attempts to retry the request
+ * in case of a redirect, authentication challenge or I/O error.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class MinimalClientExec implements ClientExecChain {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final HttpRequestExecutor requestExecutor;
+ private final HttpClientConnectionManager connManager;
+ private final ConnectionReuseStrategy reuseStrategy;
+ private final ConnectionKeepAliveStrategy keepAliveStrategy;
+ private final HttpProcessor httpProcessor;
+
+ public MinimalClientExec(
+ final HttpRequestExecutor requestExecutor,
+ final HttpClientConnectionManager connManager,
+ final ConnectionReuseStrategy reuseStrategy,
+ final ConnectionKeepAliveStrategy keepAliveStrategy) {
+ Args.notNull(requestExecutor, "HTTP request executor");
+ Args.notNull(connManager, "Client connection manager");
+ Args.notNull(reuseStrategy, "Connection reuse strategy");
+ Args.notNull(keepAliveStrategy, "Connection keep alive strategy");
+ this.httpProcessor = new ImmutableHttpProcessor(
+ new RequestContent(),
+ new RequestTargetHost(),
+ new RequestClientConnControl(),
+ new RequestUserAgent(VersionInfo.getUserAgent(
+ "Apache-HttpClient", "ch.boye.httpclientandroidlib.client", getClass())));
+ this.requestExecutor = requestExecutor;
+ this.connManager = connManager;
+ this.reuseStrategy = reuseStrategy;
+ this.keepAliveStrategy = keepAliveStrategy;
+ }
+
+ static void rewriteRequestURI(
+ final HttpRequestWrapper request,
+ final HttpRoute route) throws ProtocolException {
+ try {
+ URI uri = request.getURI();
+ if (uri != null) {
+ // Make sure the request URI is relative
+ if (uri.isAbsolute()) {
+ uri = URIUtils.rewriteURI(uri, null, true);
+ } else {
+ uri = URIUtils.rewriteURI(uri);
+ }
+ request.setURI(uri);
+ }
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException("Invalid URI: " + request.getRequestLine().getUri(), ex);
+ }
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+ Args.notNull(route, "HTTP route");
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ rewriteRequestURI(request, route);
+
+ final ConnectionRequest connRequest = connManager.requestConnection(route, null);
+ if (execAware != null) {
+ if (execAware.isAborted()) {
+ connRequest.cancel();
+ throw new RequestAbortedException("Request aborted");
+ } else {
+ execAware.setCancellable(connRequest);
+ }
+ }
+
+ final RequestConfig config = context.getRequestConfig();
+
+ final HttpClientConnection managedConn;
+ try {
+ final int timeout = config.getConnectionRequestTimeout();
+ managedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS);
+ } catch(final InterruptedException interrupted) {
+ Thread.currentThread().interrupt();
+ throw new RequestAbortedException("Request aborted", interrupted);
+ } catch(final ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ if (cause == null) {
+ cause = ex;
+ }
+ throw new RequestAbortedException("Request execution failed", cause);
+ }
+
+ final ConnectionHolder releaseTrigger = new ConnectionHolder(log, connManager, managedConn);
+ try {
+ if (execAware != null) {
+ if (execAware.isAborted()) {
+ releaseTrigger.close();
+ throw new RequestAbortedException("Request aborted");
+ } else {
+ execAware.setCancellable(releaseTrigger);
+ }
+ }
+
+ if (!managedConn.isOpen()) {
+ final int timeout = config.getConnectTimeout();
+ this.connManager.connect(
+ managedConn,
+ route,
+ timeout > 0 ? timeout : 0,
+ context);
+ this.connManager.routeComplete(managedConn, route, context);
+ }
+ final int timeout = config.getSocketTimeout();
+ if (timeout >= 0) {
+ managedConn.setSocketTimeout(timeout);
+ }
+
+ HttpHost target = null;
+ final HttpRequest original = request.getOriginal();
+ if (original instanceof HttpUriRequest) {
+ final URI uri = ((HttpUriRequest) original).getURI();
+ if (uri.isAbsolute()) {
+ target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
+ }
+ }
+ if (target == null) {
+ target = route.getTargetHost();
+ }
+
+ context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
+ context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+ context.setAttribute(HttpCoreContext.HTTP_CONNECTION, managedConn);
+ context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
+
+ httpProcessor.process(request, context);
+ final HttpResponse response = requestExecutor.execute(request, managedConn, context);
+ httpProcessor.process(response, context);
+
+ // The connection is in or can be brought to a re-usable state.
+ if (reuseStrategy.keepAlive(response, context)) {
+ // Set the idle duration of this connection
+ final long duration = keepAliveStrategy.getKeepAliveDuration(response, context);
+ releaseTrigger.setValidFor(duration, TimeUnit.MILLISECONDS);
+ releaseTrigger.markReusable();
+ } else {
+ releaseTrigger.markNonReusable();
+ }
+
+ // check for entity, release connection if possible
+ final HttpEntity entity = response.getEntity();
+ if (entity == null || !entity.isStreaming()) {
+ // connection not needed and (assumed to be) in re-usable state
+ releaseTrigger.releaseConnection();
+ return new HttpResponseProxy(response, null);
+ } else {
+ return new HttpResponseProxy(response, releaseTrigger);
+ }
+ } catch (final ConnectionShutdownException ex) {
+ final InterruptedIOException ioex = new InterruptedIOException(
+ "Connection has been shut down");
+ ioex.initCause(ex);
+ throw ioex;
+ } catch (final HttpException ex) {
+ releaseTrigger.abortConnection();
+ throw ex;
+ } catch (final IOException ex) {
+ releaseTrigger.abortConnection();
+ throw ex;
+ } catch (final RuntimeException ex) {
+ releaseTrigger.abortConnection();
+ throw ex;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ProtocolExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ProtocolExec.java
new file mode 100644
index 000000000..4effac603
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ProtocolExec.java
@@ -0,0 +1,214 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.auth.AuthScope;
+import ch.boye.httpclientandroidlib.auth.UsernamePasswordCredentials;
+import ch.boye.httpclientandroidlib.client.CredentialsProvider;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
+import ch.boye.httpclientandroidlib.client.params.ClientPNames;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.impl.client.BasicCredentialsProvider;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HttpCoreContext;
+import ch.boye.httpclientandroidlib.protocol.HttpProcessor;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Request executor in the request execution chain that is responsible
+ * for implementation of HTTP specification requirements.
+ * Internally this executor relies on a {@link HttpProcessor} to populate
+ * requisite HTTP request headers, process HTTP response headers and update
+ * session state in {@link HttpClientContext}.
+ * <p/>
+ * Further responsibilities such as communication with the opposite
+ * endpoint is delegated to the next executor in the request execution
+ * chain.
+ *
+ * @since 4.3
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class ProtocolExec implements ClientExecChain {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final ClientExecChain requestExecutor;
+ private final HttpProcessor httpProcessor;
+
+ public ProtocolExec(final ClientExecChain requestExecutor, final HttpProcessor httpProcessor) {
+ Args.notNull(requestExecutor, "HTTP client request executor");
+ Args.notNull(httpProcessor, "HTTP protocol processor");
+ this.requestExecutor = requestExecutor;
+ this.httpProcessor = httpProcessor;
+ }
+
+ void rewriteRequestURI(
+ final HttpRequestWrapper request,
+ final HttpRoute route) throws ProtocolException {
+ try {
+ URI uri = request.getURI();
+ if (uri != null) {
+ if (route.getProxyHost() != null && !route.isTunnelled()) {
+ // Make sure the request URI is absolute
+ if (!uri.isAbsolute()) {
+ final HttpHost target = route.getTargetHost();
+ uri = URIUtils.rewriteURI(uri, target, true);
+ } else {
+ uri = URIUtils.rewriteURI(uri);
+ }
+ } else {
+ // Make sure the request URI is relative
+ if (uri.isAbsolute()) {
+ uri = URIUtils.rewriteURI(uri, null, true);
+ } else {
+ uri = URIUtils.rewriteURI(uri);
+ }
+ }
+ request.setURI(uri);
+ }
+ } catch (final URISyntaxException ex) {
+ throw new ProtocolException("Invalid URI: " + request.getRequestLine().getUri(), ex);
+ }
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException,
+ HttpException {
+ Args.notNull(route, "HTTP route");
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ final HttpRequest original = request.getOriginal();
+ URI uri = null;
+ if (original instanceof HttpUriRequest) {
+ uri = ((HttpUriRequest) original).getURI();
+ } else {
+ final String uriString = original.getRequestLine().getUri();
+ try {
+ uri = URI.create(uriString);
+ } catch (final IllegalArgumentException ex) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Unable to parse '" + uriString + "' as a valid URI; " +
+ "request URI and Host header may be inconsistent", ex);
+ }
+ }
+
+ }
+ request.setURI(uri);
+
+ // Re-write request URI if needed
+ rewriteRequestURI(request, route);
+
+ final HttpParams params = request.getParams();
+ HttpHost virtualHost = (HttpHost) params.getParameter(ClientPNames.VIRTUAL_HOST);
+ // HTTPCLIENT-1092 - add the port if necessary
+ if (virtualHost != null && virtualHost.getPort() == -1) {
+ final int port = route.getTargetHost().getPort();
+ if (port != -1) {
+ virtualHost = new HttpHost(virtualHost.getHostName(), port,
+ virtualHost.getSchemeName());
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Using virtual host" + virtualHost);
+ }
+ }
+
+ HttpHost target = null;
+ if (virtualHost != null) {
+ target = virtualHost;
+ } else {
+ if (uri != null && uri.isAbsolute() && uri.getHost() != null) {
+ target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
+ }
+ }
+ if (target == null) {
+ target = route.getTargetHost();
+ }
+
+ // Get user info from the URI
+ if (uri != null) {
+ final String userinfo = uri.getUserInfo();
+ if (userinfo != null) {
+ CredentialsProvider credsProvider = context.getCredentialsProvider();
+ if (credsProvider == null) {
+ credsProvider = new BasicCredentialsProvider();
+ context.setCredentialsProvider(credsProvider);
+ }
+ credsProvider.setCredentials(
+ new AuthScope(target),
+ new UsernamePasswordCredentials(userinfo));
+ }
+ }
+
+ // Run request protocol interceptors
+ context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
+ context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
+ context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+
+ this.httpProcessor.process(request, context);
+
+ final CloseableHttpResponse response = this.requestExecutor.execute(route, request,
+ context, execAware);
+ try {
+ // Run response protocol interceptors
+ context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+ this.httpProcessor.process(response, context);
+ return response;
+ } catch (final RuntimeException ex) {
+ response.close();
+ throw ex;
+ } catch (final IOException ex) {
+ response.close();
+ throw ex;
+ } catch (final HttpException ex) {
+ response.close();
+ throw ex;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RedirectExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RedirectExec.java
new file mode 100644
index 000000000..c870662f7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RedirectExec.java
@@ -0,0 +1,185 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.auth.AuthScheme;
+import ch.boye.httpclientandroidlib.auth.AuthState;
+import ch.boye.httpclientandroidlib.client.RedirectException;
+import ch.boye.httpclientandroidlib.client.RedirectStrategy;
+import ch.boye.httpclientandroidlib.client.config.RequestConfig;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.client.utils.URIUtils;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * Request executor in the request execution chain that is responsible
+ * for handling of request redirects.
+ * <p/>
+ * Further responsibilities such as communication with the opposite
+ * endpoint is delegated to the next executor in the request execution
+ * chain.
+ *
+ * @since 4.3
+ */
+@ThreadSafe
+public class RedirectExec implements ClientExecChain {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final ClientExecChain requestExecutor;
+ private final RedirectStrategy redirectStrategy;
+ private final HttpRoutePlanner routePlanner;
+
+ public RedirectExec(
+ final ClientExecChain requestExecutor,
+ final HttpRoutePlanner routePlanner,
+ final RedirectStrategy redirectStrategy) {
+ super();
+ Args.notNull(requestExecutor, "HTTP client request executor");
+ Args.notNull(routePlanner, "HTTP route planner");
+ Args.notNull(redirectStrategy, "HTTP redirect strategy");
+ this.requestExecutor = requestExecutor;
+ this.routePlanner = routePlanner;
+ this.redirectStrategy = redirectStrategy;
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+ Args.notNull(route, "HTTP route");
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+
+ final List<URI> redirectLocations = context.getRedirectLocations();
+ if (redirectLocations != null) {
+ redirectLocations.clear();
+ }
+
+ final RequestConfig config = context.getRequestConfig();
+ final int maxRedirects = config.getMaxRedirects() > 0 ? config.getMaxRedirects() : 50;
+ HttpRoute currentRoute = route;
+ HttpRequestWrapper currentRequest = request;
+ for (int redirectCount = 0;;) {
+ final CloseableHttpResponse response = requestExecutor.execute(
+ currentRoute, currentRequest, context, execAware);
+ try {
+ if (config.isRedirectsEnabled() &&
+ this.redirectStrategy.isRedirected(currentRequest, response, context)) {
+
+ if (redirectCount >= maxRedirects) {
+ throw new RedirectException("Maximum redirects ("+ maxRedirects + ") exceeded");
+ }
+ redirectCount++;
+
+ final HttpRequest redirect = this.redirectStrategy.getRedirect(
+ currentRequest, response, context);
+ if (!redirect.headerIterator().hasNext()) {
+ final HttpRequest original = request.getOriginal();
+ redirect.setHeaders(original.getAllHeaders());
+ }
+ currentRequest = HttpRequestWrapper.wrap(redirect);
+
+ if (currentRequest instanceof HttpEntityEnclosingRequest) {
+ RequestEntityProxy.enhance((HttpEntityEnclosingRequest) currentRequest);
+ }
+
+ final URI uri = currentRequest.getURI();
+ final HttpHost newTarget = URIUtils.extractHost(uri);
+ if (newTarget == null) {
+ throw new ProtocolException("Redirect URI does not specify a valid host name: " +
+ uri);
+ }
+
+ // Reset virtual host and auth states if redirecting to another host
+ if (!currentRoute.getTargetHost().equals(newTarget)) {
+ final AuthState targetAuthState = context.getTargetAuthState();
+ if (targetAuthState != null) {
+ this.log.debug("Resetting target auth state");
+ targetAuthState.reset();
+ }
+ final AuthState proxyAuthState = context.getProxyAuthState();
+ if (proxyAuthState != null) {
+ final AuthScheme authScheme = proxyAuthState.getAuthScheme();
+ if (authScheme != null && authScheme.isConnectionBased()) {
+ this.log.debug("Resetting proxy auth state");
+ proxyAuthState.reset();
+ }
+ }
+ }
+
+ currentRoute = this.routePlanner.determineRoute(newTarget, currentRequest, context);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Redirecting to '" + uri + "' via " + currentRoute);
+ }
+ EntityUtils.consume(response.getEntity());
+ response.close();
+ } else {
+ return response;
+ }
+ } catch (final RuntimeException ex) {
+ response.close();
+ throw ex;
+ } catch (final IOException ex) {
+ response.close();
+ throw ex;
+ } catch (final HttpException ex) {
+ // Protocol exception related to a direct.
+ // The underlying connection may still be salvaged.
+ try {
+ EntityUtils.consume(response.getEntity());
+ } catch (final IOException ioex) {
+ this.log.debug("I/O error while releasing connection", ioex);
+ } finally {
+ response.close();
+ }
+ throw ex;
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestAbortedException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestAbortedException.java
new file mode 100644
index 000000000..be58be8f8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestAbortedException.java
@@ -0,0 +1,55 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.InterruptedIOException;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals that the request has been aborted.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class RequestAbortedException extends InterruptedIOException {
+
+ private static final long serialVersionUID = 4973849966012490112L;
+
+ public RequestAbortedException(final String message) {
+ super(message);
+ }
+
+ public RequestAbortedException(final String message, final Throwable cause) {
+ super(message);
+ if (cause != null) {
+ initCause(cause);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestEntityProxy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestEntityProxy.java
new file mode 100644
index 000000000..d5b396684
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RequestEntityProxy.java
@@ -0,0 +1,137 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * A Proxy class for {@link ch.boye.httpclientandroidlib.HttpEntity} enclosed in a request message.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+class RequestEntityProxy implements HttpEntity {
+
+ static void enhance(final HttpEntityEnclosingRequest request) {
+ final HttpEntity entity = request.getEntity();
+ if (entity != null && !entity.isRepeatable() && !isEnhanced(entity)) {
+ request.setEntity(new RequestEntityProxy(entity));
+ }
+ }
+
+ static boolean isEnhanced(final HttpEntity entity) {
+ return entity instanceof RequestEntityProxy;
+ }
+
+ static boolean isRepeatable(final HttpRequest request) {
+ if (request instanceof HttpEntityEnclosingRequest) {
+ final HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
+ if (entity != null) {
+ if (isEnhanced(entity)) {
+ final RequestEntityProxy proxy = (RequestEntityProxy) entity;
+ if (!proxy.isConsumed()) {
+ return true;
+ }
+ }
+ return entity.isRepeatable();
+ }
+ }
+ return true;
+ }
+
+ private final HttpEntity original;
+ private boolean consumed = false;
+
+ RequestEntityProxy(final HttpEntity original) {
+ super();
+ this.original = original;
+ }
+
+ public HttpEntity getOriginal() {
+ return original;
+ }
+
+ public boolean isConsumed() {
+ return consumed;
+ }
+
+ public boolean isRepeatable() {
+ return original.isRepeatable();
+ }
+
+ public boolean isChunked() {
+ return original.isChunked();
+ }
+
+ public long getContentLength() {
+ return original.getContentLength();
+ }
+
+ public Header getContentType() {
+ return original.getContentType();
+ }
+
+ public Header getContentEncoding() {
+ return original.getContentEncoding();
+ }
+
+ public InputStream getContent() throws IOException, IllegalStateException {
+ return original.getContent();
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ consumed = true;
+ original.writeTo(outstream);
+ }
+
+ public boolean isStreaming() {
+ return original.isStreaming();
+ }
+
+ @Deprecated
+ public void consumeContent() throws IOException {
+ consumed = true;
+ original.consumeContent();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("RequestEntityProxy{");
+ sb.append(original);
+ sb.append('}');
+ return sb.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ResponseEntityProxy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ResponseEntityProxy.java
new file mode 100644
index 000000000..8a5df1cf8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ResponseEntityProxy.java
@@ -0,0 +1,152 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.SocketException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.conn.EofSensorInputStream;
+import ch.boye.httpclientandroidlib.conn.EofSensorWatcher;
+import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper;
+
+/**
+ * A wrapper class for {@link HttpEntity} enclosed in a response message.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+class ResponseEntityProxy extends HttpEntityWrapper implements EofSensorWatcher {
+
+ private final ConnectionHolder connHolder;
+
+ public static void enchance(final HttpResponse response, final ConnectionHolder connHolder) {
+ final HttpEntity entity = response.getEntity();
+ if (entity != null && entity.isStreaming() && connHolder != null) {
+ response.setEntity(new ResponseEntityProxy(entity, connHolder));
+ }
+ }
+
+ ResponseEntityProxy(final HttpEntity entity, final ConnectionHolder connHolder) {
+ super(entity);
+ this.connHolder = connHolder;
+ }
+
+ private void cleanup() {
+ if (this.connHolder != null) {
+ this.connHolder.abortConnection();
+ }
+ }
+
+ public void releaseConnection() throws IOException {
+ if (this.connHolder != null) {
+ try {
+ if (this.connHolder.isReusable()) {
+ this.connHolder.releaseConnection();
+ }
+ } finally {
+ cleanup();
+ }
+ }
+ }
+
+ @Override
+ public boolean isRepeatable() {
+ return false;
+ }
+
+ @Override
+ public InputStream getContent() throws IOException {
+ return new EofSensorInputStream(this.wrappedEntity.getContent(), this);
+ }
+
+ @Deprecated
+ @Override
+ public void consumeContent() throws IOException {
+ releaseConnection();
+ }
+
+ @Override
+ public void writeTo(final OutputStream outstream) throws IOException {
+ try {
+ this.wrappedEntity.writeTo(outstream);
+ releaseConnection();
+ } finally {
+ cleanup();
+ }
+ }
+
+ public boolean eofDetected(final InputStream wrapped) throws IOException {
+ try {
+ // there may be some cleanup required, such as
+ // reading trailers after the response body:
+ wrapped.close();
+ releaseConnection();
+ } finally {
+ cleanup();
+ }
+ return false;
+ }
+
+ public boolean streamClosed(final InputStream wrapped) throws IOException {
+ try {
+ final boolean open = connHolder != null && !connHolder.isReleased();
+ // this assumes that closing the stream will
+ // consume the remainder of the response body:
+ try {
+ wrapped.close();
+ releaseConnection();
+ } catch (final SocketException ex) {
+ if (open) {
+ throw ex;
+ }
+ }
+ } finally {
+ cleanup();
+ }
+ return false;
+ }
+
+ public boolean streamAbort(final InputStream wrapped) throws IOException {
+ cleanup();
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("ResponseEntityProxy{");
+ sb.append(wrappedEntity);
+ sb.append('}');
+ return sb.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RetryExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RetryExec.java
new file mode 100644
index 000000000..ab78e3a83
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/RetryExec.java
@@ -0,0 +1,126 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.NoHttpResponseException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.HttpRequestRetryHandler;
+import ch.boye.httpclientandroidlib.client.NonRepeatableRequestException;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Request executor in the request execution chain that is responsible
+ * for making a decision whether a request failed due to an I/O error
+ * should be re-executed.
+ * <p/>
+ * Further responsibilities such as communication with the opposite
+ * endpoint is delegated to the next executor in the request execution
+ * chain.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class RetryExec implements ClientExecChain {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final ClientExecChain requestExecutor;
+ private final HttpRequestRetryHandler retryHandler;
+
+ public RetryExec(
+ final ClientExecChain requestExecutor,
+ final HttpRequestRetryHandler retryHandler) {
+ Args.notNull(requestExecutor, "HTTP request executor");
+ Args.notNull(retryHandler, "HTTP request retry handler");
+ this.requestExecutor = requestExecutor;
+ this.retryHandler = retryHandler;
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+ Args.notNull(route, "HTTP route");
+ Args.notNull(request, "HTTP request");
+ Args.notNull(context, "HTTP context");
+ final Header[] origheaders = request.getAllHeaders();
+ for (int execCount = 1;; execCount++) {
+ try {
+ return this.requestExecutor.execute(route, request, context, execAware);
+ } catch (final IOException ex) {
+ if (execAware != null && execAware.isAborted()) {
+ this.log.debug("Request has been aborted");
+ throw ex;
+ }
+ if (retryHandler.retryRequest(ex, execCount, context)) {
+ if (this.log.isInfoEnabled()) {
+ this.log.info("I/O exception ("+ ex.getClass().getName() +
+ ") caught when processing request to "
+ + route +
+ ": "
+ + ex.getMessage());
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug(ex.getMessage(), ex);
+ }
+ if (!RequestEntityProxy.isRepeatable(request)) {
+ this.log.debug("Cannot retry non-repeatable request");
+ throw new NonRepeatableRequestException("Cannot retry request " +
+ "with a non-repeatable request entity", ex);
+ }
+ request.setHeaders(origheaders);
+ if (this.log.isInfoEnabled()) {
+ this.log.info("Retrying request to " + route);
+ }
+ } else {
+ if (ex instanceof NoHttpResponseException) {
+ final NoHttpResponseException updatedex = new NoHttpResponseException(
+ route.getTargetHost().toHostString() + " failed to respond");
+ updatedex.setStackTrace(ex.getStackTrace());
+ throw updatedex;
+ } else {
+ throw ex;
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ServiceUnavailableRetryExec.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ServiceUnavailableRetryExec.java
new file mode 100644
index 000000000..1382d998a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/ServiceUnavailableRetryExec.java
@@ -0,0 +1,108 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+
+import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
+/* LogFactory removed by HttpClient for Android script. */
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.client.ServiceUnavailableRetryStrategy;
+import ch.boye.httpclientandroidlib.client.methods.CloseableHttpResponse;
+import ch.boye.httpclientandroidlib.client.methods.HttpExecutionAware;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestWrapper;
+import ch.boye.httpclientandroidlib.client.protocol.HttpClientContext;
+import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Request executor in the request execution chain that is responsible
+ * for making a decision whether a request that received a non-2xx response
+ * from the target server should be re-executed.
+ * <p/>
+ * Further responsibilities such as communication with the opposite
+ * endpoint is delegated to the next executor in the request execution
+ * chain.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class ServiceUnavailableRetryExec implements ClientExecChain {
+
+ public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
+
+ private final ClientExecChain requestExecutor;
+ private final ServiceUnavailableRetryStrategy retryStrategy;
+
+ public ServiceUnavailableRetryExec(
+ final ClientExecChain requestExecutor,
+ final ServiceUnavailableRetryStrategy retryStrategy) {
+ super();
+ Args.notNull(requestExecutor, "HTTP request executor");
+ Args.notNull(retryStrategy, "Retry strategy");
+ this.requestExecutor = requestExecutor;
+ this.retryStrategy = retryStrategy;
+ }
+
+ public CloseableHttpResponse execute(
+ final HttpRoute route,
+ final HttpRequestWrapper request,
+ final HttpClientContext context,
+ final HttpExecutionAware execAware) throws IOException, HttpException {
+ final Header[] origheaders = request.getAllHeaders();
+ for (int c = 1;; c++) {
+ final CloseableHttpResponse response = this.requestExecutor.execute(
+ route, request, context, execAware);
+ try {
+ if (this.retryStrategy.retryRequest(response, c, context)) {
+ response.close();
+ final long nextInterval = this.retryStrategy.getRetryInterval();
+ if (nextInterval > 0) {
+ try {
+ this.log.trace("Wait for " + nextInterval);
+ Thread.sleep(nextInterval);
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new InterruptedIOException();
+ }
+ }
+ request.setHeaders(origheaders);
+ } else {
+ return response;
+ }
+ } catch (final RuntimeException ex) {
+ response.close();
+ throw ex;
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/TunnelRefusedException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/TunnelRefusedException.java
new file mode 100644
index 000000000..5545c7b84
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/TunnelRefusedException.java
@@ -0,0 +1,55 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.execchain;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Signals that the tunnel request was rejected by the proxy host.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class TunnelRefusedException extends HttpException {
+
+ private static final long serialVersionUID = -8646722842745617323L;
+
+ private final HttpResponse response;
+
+ public TunnelRefusedException(final String message, final HttpResponse response) {
+ super(message);
+ this.response = response;
+ }
+
+ public HttpResponse getResponse() {
+ return this.response;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/package-info.java
new file mode 100644
index 000000000..740a9eec7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/execchain/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * HTTP request execution chain APIs.
+ */
+package ch.boye.httpclientandroidlib.impl.execchain;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageParser.java
new file mode 100644
index 000000000..cd7aceb52
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageParser.java
@@ -0,0 +1,284 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.MessageConstraintException;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.BasicLineParser;
+import ch.boye.httpclientandroidlib.message.LineParser;
+import ch.boye.httpclientandroidlib.params.HttpParamConfig;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract base class for HTTP message parsers that obtain input from
+ * an instance of {@link SessionInputBuffer}.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public abstract class AbstractMessageParser<T extends HttpMessage> implements HttpMessageParser<T> {
+
+ private static final int HEAD_LINE = 0;
+ private static final int HEADERS = 1;
+
+ private final SessionInputBuffer sessionBuffer;
+ private final MessageConstraints messageConstraints;
+ private final List<CharArrayBuffer> headerLines;
+ protected final LineParser lineParser;
+
+ private int state;
+ private T message;
+
+ /**
+ * Creates an instance of AbstractMessageParser.
+ *
+ * @param buffer the session input buffer.
+ * @param parser the line parser.
+ * @param params HTTP parameters.
+ *
+ * @deprecated (4.3) use {@link AbstractMessageParser#AbstractMessageParser(SessionInputBuffer,
+ * LineParser, MessageConstraints)}
+ */
+ @Deprecated
+ public AbstractMessageParser(
+ final SessionInputBuffer buffer,
+ final LineParser parser,
+ final HttpParams params) {
+ super();
+ Args.notNull(buffer, "Session input buffer");
+ Args.notNull(params, "HTTP parameters");
+ this.sessionBuffer = buffer;
+ this.messageConstraints = HttpParamConfig.getMessageConstraints(params);
+ this.lineParser = (parser != null) ? parser : BasicLineParser.INSTANCE;
+ this.headerLines = new ArrayList<CharArrayBuffer>();
+ this.state = HEAD_LINE;
+ }
+
+ /**
+ * Creates new instance of AbstractMessageParser.
+ *
+ * @param buffer the session input buffer.
+ * @param lineParser the line parser. If <code>null</code> {@link BasicLineParser#INSTANCE}
+ * will be used.
+ * @param constraints the message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ *
+ * @since 4.3
+ */
+ public AbstractMessageParser(
+ final SessionInputBuffer buffer,
+ final LineParser lineParser,
+ final MessageConstraints constraints) {
+ super();
+ this.sessionBuffer = Args.notNull(buffer, "Session input buffer");
+ this.lineParser = lineParser != null ? lineParser : BasicLineParser.INSTANCE;
+ this.messageConstraints = constraints != null ? constraints : MessageConstraints.DEFAULT;
+ this.headerLines = new ArrayList<CharArrayBuffer>();
+ this.state = HEAD_LINE;
+ }
+
+ /**
+ * Parses HTTP headers from the data receiver stream according to the generic
+ * format as given in Section 3.1 of RFC 822, RFC-2616 Section 4 and 19.3.
+ *
+ * @param inbuffer Session input buffer
+ * @param maxHeaderCount maximum number of headers allowed. If the number
+ * of headers received from the data stream exceeds maxCount value, an
+ * IOException will be thrown. Setting this parameter to a negative value
+ * or zero will disable the check.
+ * @param maxLineLen maximum number of characters for a header line,
+ * including the continuation lines. Setting this parameter to a negative
+ * value or zero will disable the check.
+ * @return array of HTTP headers
+ * @param parser line parser to use. Can be <code>null</code>, in which case
+ * the default implementation of this interface will be used.
+ *
+ * @throws IOException in case of an I/O error
+ * @throws HttpException in case of HTTP protocol violation
+ */
+ public static Header[] parseHeaders(
+ final SessionInputBuffer inbuffer,
+ final int maxHeaderCount,
+ final int maxLineLen,
+ final LineParser parser) throws HttpException, IOException {
+ final List<CharArrayBuffer> headerLines = new ArrayList<CharArrayBuffer>();
+ return parseHeaders(inbuffer, maxHeaderCount, maxLineLen,
+ parser != null ? parser : BasicLineParser.INSTANCE,
+ headerLines);
+ }
+
+ /**
+ * Parses HTTP headers from the data receiver stream according to the generic
+ * format as given in Section 3.1 of RFC 822, RFC-2616 Section 4 and 19.3.
+ *
+ * @param inbuffer Session input buffer
+ * @param maxHeaderCount maximum number of headers allowed. If the number
+ * of headers received from the data stream exceeds maxCount value, an
+ * IOException will be thrown. Setting this parameter to a negative value
+ * or zero will disable the check.
+ * @param maxLineLen maximum number of characters for a header line,
+ * including the continuation lines. Setting this parameter to a negative
+ * value or zero will disable the check.
+ * @param parser line parser to use.
+ * @param headerLines List of header lines. This list will be used to store
+ * intermediate results. This makes it possible to resume parsing of
+ * headers in case of a {@link java.io.InterruptedIOException}.
+ *
+ * @return array of HTTP headers
+ *
+ * @throws IOException in case of an I/O error
+ * @throws HttpException in case of HTTP protocol violation
+ *
+ * @since 4.1
+ */
+ public static Header[] parseHeaders(
+ final SessionInputBuffer inbuffer,
+ final int maxHeaderCount,
+ final int maxLineLen,
+ final LineParser parser,
+ final List<CharArrayBuffer> headerLines) throws HttpException, IOException {
+ Args.notNull(inbuffer, "Session input buffer");
+ Args.notNull(parser, "Line parser");
+ Args.notNull(headerLines, "Header line list");
+
+ CharArrayBuffer current = null;
+ CharArrayBuffer previous = null;
+ for (;;) {
+ if (current == null) {
+ current = new CharArrayBuffer(64);
+ } else {
+ current.clear();
+ }
+ final int l = inbuffer.readLine(current);
+ if (l == -1 || current.length() < 1) {
+ break;
+ }
+ // Parse the header name and value
+ // Check for folded headers first
+ // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
+ // discussion on folded headers
+ if ((current.charAt(0) == ' ' || current.charAt(0) == '\t') && previous != null) {
+ // we have continuation folded header
+ // so append value
+ int i = 0;
+ while (i < current.length()) {
+ final char ch = current.charAt(i);
+ if (ch != ' ' && ch != '\t') {
+ break;
+ }
+ i++;
+ }
+ if (maxLineLen > 0
+ && previous.length() + 1 + current.length() - i > maxLineLen) {
+ throw new MessageConstraintException("Maximum line length limit exceeded");
+ }
+ previous.append(' ');
+ previous.append(current, i, current.length() - i);
+ } else {
+ headerLines.add(current);
+ previous = current;
+ current = null;
+ }
+ if (maxHeaderCount > 0 && headerLines.size() >= maxHeaderCount) {
+ throw new MessageConstraintException("Maximum header count exceeded");
+ }
+ }
+ final Header[] headers = new Header[headerLines.size()];
+ for (int i = 0; i < headerLines.size(); i++) {
+ final CharArrayBuffer buffer = headerLines.get(i);
+ try {
+ headers[i] = parser.parseHeader(buffer);
+ } catch (final ParseException ex) {
+ throw new ProtocolException(ex.getMessage());
+ }
+ }
+ return headers;
+ }
+
+ /**
+ * Subclasses must override this method to generate an instance of
+ * {@link HttpMessage} based on the initial input from the session buffer.
+ * <p>
+ * Usually this method is expected to read just the very first line or
+ * the very first valid from the data stream and based on the input generate
+ * an appropriate instance of {@link HttpMessage}.
+ *
+ * @param sessionBuffer the session input buffer.
+ * @return HTTP message based on the input from the session buffer.
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation.
+ * @throws ParseException in case of a parse error.
+ */
+ protected abstract T parseHead(SessionInputBuffer sessionBuffer)
+ throws IOException, HttpException, ParseException;
+
+ public T parse() throws IOException, HttpException {
+ final int st = this.state;
+ switch (st) {
+ case HEAD_LINE:
+ try {
+ this.message = parseHead(this.sessionBuffer);
+ } catch (final ParseException px) {
+ throw new ProtocolException(px.getMessage(), px);
+ }
+ this.state = HEADERS;
+ //$FALL-THROUGH$
+ case HEADERS:
+ final Header[] headers = AbstractMessageParser.parseHeaders(
+ this.sessionBuffer,
+ this.messageConstraints.getMaxHeaderCount(),
+ this.messageConstraints.getMaxLineLength(),
+ this.lineParser,
+ this.headerLines);
+ this.message.setHeaders(headers);
+ final T result = this.message;
+ this.message = null;
+ this.headerLines.clear();
+ this.state = HEAD_LINE;
+ return result;
+ default:
+ throw new IllegalStateException("Inconsistent parser state");
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageWriter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageWriter.java
new file mode 100644
index 000000000..56caf58d5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractMessageWriter.java
@@ -0,0 +1,119 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriter;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.message.BasicLineFormatter;
+import ch.boye.httpclientandroidlib.message.LineFormatter;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract base class for HTTP message writers that serialize output to
+ * an instance of {@link SessionOutputBuffer}.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public abstract class AbstractMessageWriter<T extends HttpMessage> implements HttpMessageWriter<T> {
+
+ protected final SessionOutputBuffer sessionBuffer;
+ protected final CharArrayBuffer lineBuf;
+ protected final LineFormatter lineFormatter;
+
+ /**
+ * Creates an instance of AbstractMessageWriter.
+ *
+ * @param buffer the session output buffer.
+ * @param formatter the line formatter.
+ * @param params HTTP parameters.
+ *
+ * @deprecated (4.3) use
+ * {@link AbstractMessageWriter#AbstractMessageWriter(SessionOutputBuffer, LineFormatter)}
+ */
+ @Deprecated
+ public AbstractMessageWriter(final SessionOutputBuffer buffer,
+ final LineFormatter formatter,
+ final HttpParams params) {
+ super();
+ Args.notNull(buffer, "Session input buffer");
+ this.sessionBuffer = buffer;
+ this.lineBuf = new CharArrayBuffer(128);
+ this.lineFormatter = (formatter != null) ? formatter : BasicLineFormatter.INSTANCE;
+ }
+
+ /**
+ * Creates an instance of AbstractMessageWriter.
+ *
+ * @param buffer the session output buffer.
+ * @param formatter the line formatter If <code>null</code> {@link BasicLineFormatter#INSTANCE}
+ * will be used.
+ *
+ * @since 4.3
+ */
+ public AbstractMessageWriter(
+ final SessionOutputBuffer buffer,
+ final LineFormatter formatter) {
+ super();
+ this.sessionBuffer = Args.notNull(buffer, "Session input buffer");
+ this.lineFormatter = (formatter != null) ? formatter : BasicLineFormatter.INSTANCE;
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ /**
+ * Subclasses must override this method to write out the first header line
+ * based on the {@link HttpMessage} passed as a parameter.
+ *
+ * @param message the message whose first line is to be written out.
+ * @throws IOException in case of an I/O error.
+ */
+ protected abstract void writeHeadLine(T message) throws IOException;
+
+ public void write(final T message) throws IOException, HttpException {
+ Args.notNull(message, "HTTP message");
+ writeHeadLine(message);
+ for (final HeaderIterator it = message.headerIterator(); it.hasNext(); ) {
+ final Header header = it.nextHeader();
+ this.sessionBuffer.writeLine
+ (lineFormatter.formatHeader(this.lineBuf, header));
+ }
+ this.lineBuf.clear();
+ this.sessionBuffer.writeLine(this.lineBuf);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java
new file mode 100644
index 000000000..e53e07a30
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java
@@ -0,0 +1,401 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.BufferInfo;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.ByteArrayBuffer;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract base class for session input buffers that stream data from
+ * an arbitrary {@link InputStream}. This class buffers input data in
+ * an internal byte array for optimal input performance.
+ * <p>
+ * {@link #readLine(CharArrayBuffer)} and {@link #readLine()} methods of this
+ * class treat a lone LF as valid line delimiters in addition to CR-LF required
+ * by the HTTP specification.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link SessionInputBufferImpl}
+ */
+@NotThreadSafe
+@Deprecated
+public abstract class AbstractSessionInputBuffer implements SessionInputBuffer, BufferInfo {
+
+ private InputStream instream;
+ private byte[] buffer;
+ private ByteArrayBuffer linebuffer;
+ private Charset charset;
+ private boolean ascii;
+ private int maxLineLen;
+ private int minChunkLimit;
+ private HttpTransportMetricsImpl metrics;
+ private CodingErrorAction onMalformedCharAction;
+ private CodingErrorAction onUnmappableCharAction;
+
+ private int bufferpos;
+ private int bufferlen;
+ private CharsetDecoder decoder;
+ private CharBuffer cbuf;
+
+ public AbstractSessionInputBuffer() {
+ }
+
+ /**
+ * Initializes this session input buffer.
+ *
+ * @param instream the source input stream.
+ * @param buffersize the size of the internal buffer.
+ * @param params HTTP parameters.
+ */
+ protected void init(final InputStream instream, final int buffersize, final HttpParams params) {
+ Args.notNull(instream, "Input stream");
+ Args.notNegative(buffersize, "Buffer size");
+ Args.notNull(params, "HTTP parameters");
+ this.instream = instream;
+ this.buffer = new byte[buffersize];
+ this.bufferpos = 0;
+ this.bufferlen = 0;
+ this.linebuffer = new ByteArrayBuffer(buffersize);
+ final String charset = (String) params.getParameter(CoreProtocolPNames.HTTP_ELEMENT_CHARSET);
+ this.charset = charset != null ? Charset.forName(charset) : Consts.ASCII;
+ this.ascii = this.charset.equals(Consts.ASCII);
+ this.decoder = null;
+ this.maxLineLen = params.getIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, -1);
+ this.minChunkLimit = params.getIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 512);
+ this.metrics = createTransportMetrics();
+ final CodingErrorAction a1 = (CodingErrorAction) params.getParameter(
+ CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION);
+ this.onMalformedCharAction = a1 != null ? a1 : CodingErrorAction.REPORT;
+ final CodingErrorAction a2 = (CodingErrorAction) params.getParameter(
+ CoreProtocolPNames.HTTP_UNMAPPABLE_INPUT_ACTION);
+ this.onUnmappableCharAction = a2 != null? a2 : CodingErrorAction.REPORT;
+ }
+
+ /**
+ * @since 4.1
+ */
+ protected HttpTransportMetricsImpl createTransportMetrics() {
+ return new HttpTransportMetricsImpl();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int capacity() {
+ return this.buffer.length;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int length() {
+ return this.bufferlen - this.bufferpos;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int available() {
+ return capacity() - length();
+ }
+
+ protected int fillBuffer() throws IOException {
+ // compact the buffer if necessary
+ if (this.bufferpos > 0) {
+ final int len = this.bufferlen - this.bufferpos;
+ if (len > 0) {
+ System.arraycopy(this.buffer, this.bufferpos, this.buffer, 0, len);
+ }
+ this.bufferpos = 0;
+ this.bufferlen = len;
+ }
+ final int l;
+ final int off = this.bufferlen;
+ final int len = this.buffer.length - off;
+ l = this.instream.read(this.buffer, off, len);
+ if (l == -1) {
+ return -1;
+ } else {
+ this.bufferlen = off + l;
+ this.metrics.incrementBytesTransferred(l);
+ return l;
+ }
+ }
+
+ protected boolean hasBufferedData() {
+ return this.bufferpos < this.bufferlen;
+ }
+
+ public int read() throws IOException {
+ int noRead;
+ while (!hasBufferedData()) {
+ noRead = fillBuffer();
+ if (noRead == -1) {
+ return -1;
+ }
+ }
+ return this.buffer[this.bufferpos++] & 0xff;
+ }
+
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ if (b == null) {
+ return 0;
+ }
+ if (hasBufferedData()) {
+ final int chunk = Math.min(len, this.bufferlen - this.bufferpos);
+ System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
+ this.bufferpos += chunk;
+ return chunk;
+ }
+ // If the remaining capacity is big enough, read directly from the
+ // underlying input stream bypassing the buffer.
+ if (len > this.minChunkLimit) {
+ final int read = this.instream.read(b, off, len);
+ if (read > 0) {
+ this.metrics.incrementBytesTransferred(read);
+ }
+ return read;
+ } else {
+ // otherwise read to the buffer first
+ while (!hasBufferedData()) {
+ final int noRead = fillBuffer();
+ if (noRead == -1) {
+ return -1;
+ }
+ }
+ final int chunk = Math.min(len, this.bufferlen - this.bufferpos);
+ System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
+ this.bufferpos += chunk;
+ return chunk;
+ }
+ }
+
+ public int read(final byte[] b) throws IOException {
+ if (b == null) {
+ return 0;
+ }
+ return read(b, 0, b.length);
+ }
+
+ private int locateLF() {
+ for (int i = this.bufferpos; i < this.bufferlen; i++) {
+ if (this.buffer[i] == HTTP.LF) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Reads a complete line of characters up to a line delimiter from this
+ * session buffer into the given line buffer. The number of chars actually
+ * read is returned as an integer. The line delimiter itself is discarded.
+ * If no char is available because the end of the stream has been reached,
+ * the value <code>-1</code> is returned. This method blocks until input
+ * data is available, end of file is detected, or an exception is thrown.
+ * <p>
+ * This method treats a lone LF as a valid line delimiters in addition
+ * to CR-LF required by the HTTP specification.
+ *
+ * @param charbuffer the line buffer.
+ * @return one line of characters
+ * @exception IOException if an I/O error occurs.
+ */
+ public int readLine(final CharArrayBuffer charbuffer) throws IOException {
+ Args.notNull(charbuffer, "Char array buffer");
+ int noRead = 0;
+ boolean retry = true;
+ while (retry) {
+ // attempt to find end of line (LF)
+ final int i = locateLF();
+ if (i != -1) {
+ // end of line found.
+ if (this.linebuffer.isEmpty()) {
+ // the entire line is preset in the read buffer
+ return lineFromReadBuffer(charbuffer, i);
+ }
+ retry = false;
+ final int len = i + 1 - this.bufferpos;
+ this.linebuffer.append(this.buffer, this.bufferpos, len);
+ this.bufferpos = i + 1;
+ } else {
+ // end of line not found
+ if (hasBufferedData()) {
+ final int len = this.bufferlen - this.bufferpos;
+ this.linebuffer.append(this.buffer, this.bufferpos, len);
+ this.bufferpos = this.bufferlen;
+ }
+ noRead = fillBuffer();
+ if (noRead == -1) {
+ retry = false;
+ }
+ }
+ if (this.maxLineLen > 0 && this.linebuffer.length() >= this.maxLineLen) {
+ throw new IOException("Maximum line length limit exceeded");
+ }
+ }
+ if (noRead == -1 && this.linebuffer.isEmpty()) {
+ // indicate the end of stream
+ return -1;
+ }
+ return lineFromLineBuffer(charbuffer);
+ }
+
+ /**
+ * Reads a complete line of characters up to a line delimiter from this
+ * session buffer. The line delimiter itself is discarded. If no char is
+ * available because the end of the stream has been reached,
+ * <code>null</code> is returned. This method blocks until input data is
+ * available, end of file is detected, or an exception is thrown.
+ * <p>
+ * This method treats a lone LF as a valid line delimiters in addition
+ * to CR-LF required by the HTTP specification.
+ *
+ * @return HTTP line as a string
+ * @exception IOException if an I/O error occurs.
+ */
+ private int lineFromLineBuffer(final CharArrayBuffer charbuffer)
+ throws IOException {
+ // discard LF if found
+ int len = this.linebuffer.length();
+ if (len > 0) {
+ if (this.linebuffer.byteAt(len - 1) == HTTP.LF) {
+ len--;
+ }
+ // discard CR if found
+ if (len > 0) {
+ if (this.linebuffer.byteAt(len - 1) == HTTP.CR) {
+ len--;
+ }
+ }
+ }
+ if (this.ascii) {
+ charbuffer.append(this.linebuffer, 0, len);
+ } else {
+ final ByteBuffer bbuf = ByteBuffer.wrap(this.linebuffer.buffer(), 0, len);
+ len = appendDecoded(charbuffer, bbuf);
+ }
+ this.linebuffer.clear();
+ return len;
+ }
+
+ private int lineFromReadBuffer(final CharArrayBuffer charbuffer, final int position)
+ throws IOException {
+ final int off = this.bufferpos;
+ int i = position;
+ this.bufferpos = i + 1;
+ if (i > off && this.buffer[i - 1] == HTTP.CR) {
+ // skip CR if found
+ i--;
+ }
+ int len = i - off;
+ if (this.ascii) {
+ charbuffer.append(this.buffer, off, len);
+ } else {
+ final ByteBuffer bbuf = ByteBuffer.wrap(this.buffer, off, len);
+ len = appendDecoded(charbuffer, bbuf);
+ }
+ return len;
+ }
+
+ private int appendDecoded(
+ final CharArrayBuffer charbuffer, final ByteBuffer bbuf) throws IOException {
+ if (!bbuf.hasRemaining()) {
+ return 0;
+ }
+ if (this.decoder == null) {
+ this.decoder = this.charset.newDecoder();
+ this.decoder.onMalformedInput(this.onMalformedCharAction);
+ this.decoder.onUnmappableCharacter(this.onUnmappableCharAction);
+ }
+ if (this.cbuf == null) {
+ this.cbuf = CharBuffer.allocate(1024);
+ }
+ this.decoder.reset();
+ int len = 0;
+ while (bbuf.hasRemaining()) {
+ final CoderResult result = this.decoder.decode(bbuf, this.cbuf, true);
+ len += handleDecodingResult(result, charbuffer, bbuf);
+ }
+ final CoderResult result = this.decoder.flush(this.cbuf);
+ len += handleDecodingResult(result, charbuffer, bbuf);
+ this.cbuf.clear();
+ return len;
+ }
+
+ private int handleDecodingResult(
+ final CoderResult result,
+ final CharArrayBuffer charbuffer,
+ final ByteBuffer bbuf) throws IOException {
+ if (result.isError()) {
+ result.throwException();
+ }
+ this.cbuf.flip();
+ final int len = this.cbuf.remaining();
+ while (this.cbuf.hasRemaining()) {
+ charbuffer.append(this.cbuf.get());
+ }
+ this.cbuf.compact();
+ return len;
+ }
+
+ public String readLine() throws IOException {
+ final CharArrayBuffer charbuffer = new CharArrayBuffer(64);
+ final int l = readLine(charbuffer);
+ if (l != -1) {
+ return charbuffer.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public HttpTransportMetrics getMetrics() {
+ return this.metrics;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java
new file mode 100644
index 000000000..a2c87d084
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java
@@ -0,0 +1,307 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+import ch.boye.httpclientandroidlib.Consts;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.BufferInfo;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.ByteArrayBuffer;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract base class for session output buffers that stream data to
+ * an arbitrary {@link OutputStream}. This class buffers small chunks of
+ * output data in an internal byte array for optimal output performance.
+ * </p>
+ * {@link #writeLine(CharArrayBuffer)} and {@link #writeLine(String)} methods
+ * of this class use CR-LF as a line delimiter.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link SessionOutputBufferImpl}
+ */
+@NotThreadSafe
+@Deprecated
+public abstract class AbstractSessionOutputBuffer implements SessionOutputBuffer, BufferInfo {
+
+ private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
+
+ private OutputStream outstream;
+ private ByteArrayBuffer buffer;
+ private Charset charset;
+ private boolean ascii;
+ private int minChunkLimit;
+ private HttpTransportMetricsImpl metrics;
+ private CodingErrorAction onMalformedCharAction;
+ private CodingErrorAction onUnmappableCharAction;
+
+ private CharsetEncoder encoder;
+ private ByteBuffer bbuf;
+
+ protected AbstractSessionOutputBuffer(
+ final OutputStream outstream,
+ final int buffersize,
+ final Charset charset,
+ final int minChunkLimit,
+ final CodingErrorAction malformedCharAction,
+ final CodingErrorAction unmappableCharAction) {
+ super();
+ Args.notNull(outstream, "Input stream");
+ Args.notNegative(buffersize, "Buffer size");
+ this.outstream = outstream;
+ this.buffer = new ByteArrayBuffer(buffersize);
+ this.charset = charset != null ? charset : Consts.ASCII;
+ this.ascii = this.charset.equals(Consts.ASCII);
+ this.encoder = null;
+ this.minChunkLimit = minChunkLimit >= 0 ? minChunkLimit : 512;
+ this.metrics = createTransportMetrics();
+ this.onMalformedCharAction = malformedCharAction != null ? malformedCharAction :
+ CodingErrorAction.REPORT;
+ this.onUnmappableCharAction = unmappableCharAction != null? unmappableCharAction :
+ CodingErrorAction.REPORT;
+ }
+
+ public AbstractSessionOutputBuffer() {
+ }
+
+ protected void init(final OutputStream outstream, final int buffersize, final HttpParams params) {
+ Args.notNull(outstream, "Input stream");
+ Args.notNegative(buffersize, "Buffer size");
+ Args.notNull(params, "HTTP parameters");
+ this.outstream = outstream;
+ this.buffer = new ByteArrayBuffer(buffersize);
+ final String charset = (String) params.getParameter(CoreProtocolPNames.HTTP_ELEMENT_CHARSET);
+ this.charset = charset != null ? Charset.forName(charset) : Consts.ASCII;
+ this.ascii = this.charset.equals(Consts.ASCII);
+ this.encoder = null;
+ this.minChunkLimit = params.getIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 512);
+ this.metrics = createTransportMetrics();
+ final CodingErrorAction a1 = (CodingErrorAction) params.getParameter(
+ CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION);
+ this.onMalformedCharAction = a1 != null ? a1 : CodingErrorAction.REPORT;
+ final CodingErrorAction a2 = (CodingErrorAction) params.getParameter(
+ CoreProtocolPNames.HTTP_UNMAPPABLE_INPUT_ACTION);
+ this.onUnmappableCharAction = a2 != null? a2 : CodingErrorAction.REPORT;
+ }
+
+ /**
+ * @since 4.1
+ */
+ protected HttpTransportMetricsImpl createTransportMetrics() {
+ return new HttpTransportMetricsImpl();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int capacity() {
+ return this.buffer.capacity();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int length() {
+ return this.buffer.length();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public int available() {
+ return capacity() - length();
+ }
+
+ protected void flushBuffer() throws IOException {
+ final int len = this.buffer.length();
+ if (len > 0) {
+ this.outstream.write(this.buffer.buffer(), 0, len);
+ this.buffer.clear();
+ this.metrics.incrementBytesTransferred(len);
+ }
+ }
+
+ public void flush() throws IOException {
+ flushBuffer();
+ this.outstream.flush();
+ }
+
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ if (b == null) {
+ return;
+ }
+ // Do not want to buffer large-ish chunks
+ // if the byte array is larger then MIN_CHUNK_LIMIT
+ // write it directly to the output stream
+ if (len > this.minChunkLimit || len > this.buffer.capacity()) {
+ // flush the buffer
+ flushBuffer();
+ // write directly to the out stream
+ this.outstream.write(b, off, len);
+ this.metrics.incrementBytesTransferred(len);
+ } else {
+ // Do not let the buffer grow unnecessarily
+ final int freecapacity = this.buffer.capacity() - this.buffer.length();
+ if (len > freecapacity) {
+ // flush the buffer
+ flushBuffer();
+ }
+ // buffer
+ this.buffer.append(b, off, len);
+ }
+ }
+
+ public void write(final byte[] b) throws IOException {
+ if (b == null) {
+ return;
+ }
+ write(b, 0, b.length);
+ }
+
+ public void write(final int b) throws IOException {
+ if (this.buffer.isFull()) {
+ flushBuffer();
+ }
+ this.buffer.append(b);
+ }
+
+ /**
+ * Writes characters from the specified string followed by a line delimiter
+ * to this session buffer.
+ * <p>
+ * This method uses CR-LF as a line delimiter.
+ *
+ * @param s the line.
+ * @exception IOException if an I/O error occurs.
+ */
+ public void writeLine(final String s) throws IOException {
+ if (s == null) {
+ return;
+ }
+ if (s.length() > 0) {
+ if (this.ascii) {
+ for (int i = 0; i < s.length(); i++) {
+ write(s.charAt(i));
+ }
+ } else {
+ final CharBuffer cbuf = CharBuffer.wrap(s);
+ writeEncoded(cbuf);
+ }
+ }
+ write(CRLF);
+ }
+
+ /**
+ * Writes characters from the specified char array followed by a line
+ * delimiter to this session buffer.
+ * <p>
+ * This method uses CR-LF as a line delimiter.
+ *
+ * @param charbuffer the buffer containing chars of the line.
+ * @exception IOException if an I/O error occurs.
+ */
+ public void writeLine(final CharArrayBuffer charbuffer) throws IOException {
+ if (charbuffer == null) {
+ return;
+ }
+ if (this.ascii) {
+ int off = 0;
+ int remaining = charbuffer.length();
+ while (remaining > 0) {
+ int chunk = this.buffer.capacity() - this.buffer.length();
+ chunk = Math.min(chunk, remaining);
+ if (chunk > 0) {
+ this.buffer.append(charbuffer, off, chunk);
+ }
+ if (this.buffer.isFull()) {
+ flushBuffer();
+ }
+ off += chunk;
+ remaining -= chunk;
+ }
+ } else {
+ final CharBuffer cbuf = CharBuffer.wrap(charbuffer.buffer(), 0, charbuffer.length());
+ writeEncoded(cbuf);
+ }
+ write(CRLF);
+ }
+
+ private void writeEncoded(final CharBuffer cbuf) throws IOException {
+ if (!cbuf.hasRemaining()) {
+ return;
+ }
+ if (this.encoder == null) {
+ this.encoder = this.charset.newEncoder();
+ this.encoder.onMalformedInput(this.onMalformedCharAction);
+ this.encoder.onUnmappableCharacter(this.onUnmappableCharAction);
+ }
+ if (this.bbuf == null) {
+ this.bbuf = ByteBuffer.allocate(1024);
+ }
+ this.encoder.reset();
+ while (cbuf.hasRemaining()) {
+ final CoderResult result = this.encoder.encode(cbuf, this.bbuf, true);
+ handleEncodingResult(result);
+ }
+ final CoderResult result = this.encoder.flush(this.bbuf);
+ handleEncodingResult(result);
+ this.bbuf.clear();
+ }
+
+ private void handleEncodingResult(final CoderResult result) throws IOException {
+ if (result.isError()) {
+ result.throwException();
+ }
+ this.bbuf.flip();
+ while (this.bbuf.hasRemaining()) {
+ write(this.bbuf.get());
+ }
+ this.bbuf.compact();
+ }
+
+ public HttpTransportMetrics getMetrics() {
+ return this.metrics;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedInputStream.java
new file mode 100644
index 000000000..447bd676d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedInputStream.java
@@ -0,0 +1,301 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.MalformedChunkCodingException;
+import ch.boye.httpclientandroidlib.TruncatedChunkException;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.BufferInfo;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Implements chunked transfer coding. The content is received in small chunks.
+ * Entities transferred using this input stream can be of unlimited length.
+ * After the stream is read to the end, it provides access to the trailers,
+ * if any.
+ * <p>
+ * Note that this class NEVER closes the underlying stream, even when close
+ * gets called. Instead, it will read until the "end" of its chunking on
+ * close, which allows for the seamless execution of subsequent HTTP 1.1
+ * requests, while not requiring the client to remember to read the entire
+ * contents of the response.
+ *
+ *
+ * @since 4.0
+ *
+ */
+@NotThreadSafe
+public class ChunkedInputStream extends InputStream {
+
+ private static final int CHUNK_LEN = 1;
+ private static final int CHUNK_DATA = 2;
+ private static final int CHUNK_CRLF = 3;
+
+ private static final int BUFFER_SIZE = 2048;
+
+ /** The session input buffer */
+ private final SessionInputBuffer in;
+
+ private final CharArrayBuffer buffer;
+
+ private int state;
+
+ /** The chunk size */
+ private int chunkSize;
+
+ /** The current position within the current chunk */
+ private int pos;
+
+ /** True if we've reached the end of stream */
+ private boolean eof = false;
+
+ /** True if this stream is closed */
+ private boolean closed = false;
+
+ private Header[] footers = new Header[] {};
+
+ /**
+ * Wraps session input stream and reads chunk coded input.
+ *
+ * @param in The session input buffer
+ */
+ public ChunkedInputStream(final SessionInputBuffer in) {
+ super();
+ this.in = Args.notNull(in, "Session input buffer");
+ this.pos = 0;
+ this.buffer = new CharArrayBuffer(16);
+ this.state = CHUNK_LEN;
+ }
+
+ @Override
+ public int available() throws IOException {
+ if (this.in instanceof BufferInfo) {
+ final int len = ((BufferInfo) this.in).length();
+ return Math.min(len, this.chunkSize - this.pos);
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * <p> Returns all the data in a chunked stream in coalesced form. A chunk
+ * is followed by a CRLF. The method returns -1 as soon as a chunksize of 0
+ * is detected.</p>
+ *
+ * <p> Trailer headers are read automatically at the end of the stream and
+ * can be obtained with the getResponseFooters() method.</p>
+ *
+ * @return -1 of the end of the stream has been reached or the next data
+ * byte
+ * @throws IOException in case of an I/O error
+ */
+ @Override
+ public int read() throws IOException {
+ if (this.closed) {
+ throw new IOException("Attempted read from closed stream.");
+ }
+ if (this.eof) {
+ return -1;
+ }
+ if (state != CHUNK_DATA) {
+ nextChunk();
+ if (this.eof) {
+ return -1;
+ }
+ }
+ final int b = in.read();
+ if (b != -1) {
+ pos++;
+ if (pos >= chunkSize) {
+ state = CHUNK_CRLF;
+ }
+ }
+ return b;
+ }
+
+ /**
+ * Read some bytes from the stream.
+ * @param b The byte array that will hold the contents from the stream.
+ * @param off The offset into the byte array at which bytes will start to be
+ * placed.
+ * @param len the maximum number of bytes that can be returned.
+ * @return The number of bytes returned or -1 if the end of stream has been
+ * reached.
+ * @throws IOException in case of an I/O error
+ */
+ @Override
+ public int read (final byte[] b, final int off, final int len) throws IOException {
+
+ if (closed) {
+ throw new IOException("Attempted read from closed stream.");
+ }
+
+ if (eof) {
+ return -1;
+ }
+ if (state != CHUNK_DATA) {
+ nextChunk();
+ if (eof) {
+ return -1;
+ }
+ }
+ final int bytesRead = in.read(b, off, Math.min(len, chunkSize - pos));
+ if (bytesRead != -1) {
+ pos += bytesRead;
+ if (pos >= chunkSize) {
+ state = CHUNK_CRLF;
+ }
+ return bytesRead;
+ } else {
+ eof = true;
+ throw new TruncatedChunkException("Truncated chunk "
+ + "( expected size: " + chunkSize
+ + "; actual size: " + pos + ")");
+ }
+ }
+
+ /**
+ * Read some bytes from the stream.
+ * @param b The byte array that will hold the contents from the stream.
+ * @return The number of bytes returned or -1 if the end of stream has been
+ * reached.
+ * @throws IOException in case of an I/O error
+ */
+ @Override
+ public int read (final byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Read the next chunk.
+ * @throws IOException in case of an I/O error
+ */
+ private void nextChunk() throws IOException {
+ chunkSize = getChunkSize();
+ if (chunkSize < 0) {
+ throw new MalformedChunkCodingException("Negative chunk size");
+ }
+ state = CHUNK_DATA;
+ pos = 0;
+ if (chunkSize == 0) {
+ eof = true;
+ parseTrailerHeaders();
+ }
+ }
+
+ /**
+ * Expects the stream to start with a chunksize in hex with optional
+ * comments after a semicolon. The line must end with a CRLF: "a3; some
+ * comment\r\n" Positions the stream at the start of the next line.
+ */
+ private int getChunkSize() throws IOException {
+ final int st = this.state;
+ switch (st) {
+ case CHUNK_CRLF:
+ this.buffer.clear();
+ final int bytesRead1 = this.in.readLine(this.buffer);
+ if (bytesRead1 == -1) {
+ return 0;
+ }
+ if (!this.buffer.isEmpty()) {
+ throw new MalformedChunkCodingException(
+ "Unexpected content at the end of chunk");
+ }
+ state = CHUNK_LEN;
+ //$FALL-THROUGH$
+ case CHUNK_LEN:
+ this.buffer.clear();
+ final int bytesRead2 = this.in.readLine(this.buffer);
+ if (bytesRead2 == -1) {
+ return 0;
+ }
+ int separator = this.buffer.indexOf(';');
+ if (separator < 0) {
+ separator = this.buffer.length();
+ }
+ try {
+ return Integer.parseInt(this.buffer.substringTrimmed(0, separator), 16);
+ } catch (final NumberFormatException e) {
+ throw new MalformedChunkCodingException("Bad chunk header");
+ }
+ default:
+ throw new IllegalStateException("Inconsistent codec state");
+ }
+ }
+
+ /**
+ * Reads and stores the Trailer headers.
+ * @throws IOException in case of an I/O error
+ */
+ private void parseTrailerHeaders() throws IOException {
+ try {
+ this.footers = AbstractMessageParser.parseHeaders
+ (in, -1, -1, null);
+ } catch (final HttpException ex) {
+ final IOException ioe = new MalformedChunkCodingException("Invalid footer: "
+ + ex.getMessage());
+ ioe.initCause(ex);
+ throw ioe;
+ }
+ }
+
+ /**
+ * Upon close, this reads the remainder of the chunked message,
+ * leaving the underlying socket at a position to start reading the
+ * next response without scanning.
+ * @throws IOException in case of an I/O error
+ */
+ @Override
+ public void close() throws IOException {
+ if (!closed) {
+ try {
+ if (!eof) {
+ // read and discard the remainder of the message
+ final byte buff[] = new byte[BUFFER_SIZE];
+ while (read(buff) >= 0) {
+ }
+ }
+ } finally {
+ eof = true;
+ closed = true;
+ }
+ }
+ }
+
+ public Header[] getFooters() {
+ return this.footers.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedOutputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedOutputStream.java
new file mode 100644
index 000000000..828df923c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ChunkedOutputStream.java
@@ -0,0 +1,208 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+
+/**
+ * Implements chunked transfer coding. The content is sent in small chunks.
+ * Entities transferred using this output stream can be of unlimited length.
+ * Writes are buffered to an internal buffer (2048 default size).
+ * <p>
+ * Note that this class NEVER closes the underlying stream, even when close
+ * gets called. Instead, the stream will be marked as closed and no further
+ * output will be permitted.
+ *
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class ChunkedOutputStream extends OutputStream {
+
+ // ----------------------------------------------------- Instance Variables
+ private final SessionOutputBuffer out;
+
+ private final byte[] cache;
+
+ private int cachePosition = 0;
+
+ private boolean wroteLastChunk = false;
+
+ /** True if the stream is closed. */
+ private boolean closed = false;
+
+ /**
+ * Wraps a session output buffer and chunk-encodes the output.
+ *
+ * @param out The session output buffer
+ * @param bufferSize The minimum chunk size (excluding last chunk)
+ * @throws IOException not thrown
+ *
+ * @deprecated (4.3) use {@link ChunkedOutputStream#ChunkedOutputStream(int, SessionOutputBuffer)}
+ */
+ @Deprecated
+ public ChunkedOutputStream(final SessionOutputBuffer out, final int bufferSize)
+ throws IOException {
+ this(bufferSize, out);
+ }
+
+ /**
+ * Wraps a session output buffer and chunks the output. The default buffer
+ * size of 2048 was chosen because the chunk overhead is less than 0.5%
+ *
+ * @param out the output buffer to wrap
+ * @throws IOException not thrown
+ *
+ * @deprecated (4.3) use {@link ChunkedOutputStream#ChunkedOutputStream(int, SessionOutputBuffer)}
+ */
+ @Deprecated
+ public ChunkedOutputStream(final SessionOutputBuffer out)
+ throws IOException {
+ this(2048, out);
+ }
+
+ /**
+ * Wraps a session output buffer and chunk-encodes the output.
+ *
+ * @param bufferSize The minimum chunk size (excluding last chunk)
+ * @param out The session output buffer
+ */
+ public ChunkedOutputStream(final int bufferSize, final SessionOutputBuffer out) {
+ super();
+ this.cache = new byte[bufferSize];
+ this.out = out;
+ }
+
+ /**
+ * Writes the cache out onto the underlying stream
+ */
+ protected void flushCache() throws IOException {
+ if (this.cachePosition > 0) {
+ this.out.writeLine(Integer.toHexString(this.cachePosition));
+ this.out.write(this.cache, 0, this.cachePosition);
+ this.out.writeLine("");
+ this.cachePosition = 0;
+ }
+ }
+
+ /**
+ * Writes the cache and bufferToAppend to the underlying stream
+ * as one large chunk
+ */
+ protected void flushCacheWithAppend(final byte bufferToAppend[], final int off, final int len) throws IOException {
+ this.out.writeLine(Integer.toHexString(this.cachePosition + len));
+ this.out.write(this.cache, 0, this.cachePosition);
+ this.out.write(bufferToAppend, off, len);
+ this.out.writeLine("");
+ this.cachePosition = 0;
+ }
+
+ protected void writeClosingChunk() throws IOException {
+ // Write the final chunk.
+ this.out.writeLine("0");
+ this.out.writeLine("");
+ }
+
+ // ----------------------------------------------------------- Public Methods
+ /**
+ * Must be called to ensure the internal cache is flushed and the closing
+ * chunk is written.
+ * @throws IOException in case of an I/O error
+ */
+ public void finish() throws IOException {
+ if (!this.wroteLastChunk) {
+ flushCache();
+ writeClosingChunk();
+ this.wroteLastChunk = true;
+ }
+ }
+
+ // -------------------------------------------- OutputStream Methods
+ @Override
+ public void write(final int b) throws IOException {
+ if (this.closed) {
+ throw new IOException("Attempted write to closed stream.");
+ }
+ this.cache[this.cachePosition] = (byte) b;
+ this.cachePosition++;
+ if (this.cachePosition == this.cache.length) {
+ flushCache();
+ }
+ }
+
+ /**
+ * Writes the array. If the array does not fit within the buffer, it is
+ * not split, but rather written out as one large chunk.
+ */
+ @Override
+ public void write(final byte b[]) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ /**
+ * Writes the array. If the array does not fit within the buffer, it is
+ * not split, but rather written out as one large chunk.
+ */
+ @Override
+ public void write(final byte src[], final int off, final int len) throws IOException {
+ if (this.closed) {
+ throw new IOException("Attempted write to closed stream.");
+ }
+ if (len >= this.cache.length - this.cachePosition) {
+ flushCacheWithAppend(src, off, len);
+ } else {
+ System.arraycopy(src, off, cache, this.cachePosition, len);
+ this.cachePosition += len;
+ }
+ }
+
+ /**
+ * Flushes the content buffer and the underlying stream.
+ */
+ @Override
+ public void flush() throws IOException {
+ flushCache();
+ this.out.flush();
+ }
+
+ /**
+ * Finishes writing to the underlying stream, but does NOT close the underlying stream.
+ */
+ @Override
+ public void close() throws IOException {
+ if (!this.closed) {
+ this.closed = true;
+ finish();
+ this.out.flush();
+ }
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthInputStream.java
new file mode 100644
index 000000000..65a271cb8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthInputStream.java
@@ -0,0 +1,232 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.ConnectionClosedException;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.BufferInfo;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Input stream that cuts off after a defined number of bytes. This class
+ * is used to receive content of HTTP messages where the end of the content
+ * entity is determined by the value of the <code>Content-Length header</code>.
+ * Entities transferred using this stream can be maximum {@link Long#MAX_VALUE}
+ * long.
+ * <p>
+ * Note that this class NEVER closes the underlying stream, even when close
+ * gets called. Instead, it will read until the "end" of its limit on
+ * close, which allows for the seamless execution of subsequent HTTP 1.1
+ * requests, while not requiring the client to remember to read the entire
+ * contents of the response.
+ *
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class ContentLengthInputStream extends InputStream {
+
+ private static final int BUFFER_SIZE = 2048;
+ /**
+ * The maximum number of bytes that can be read from the stream. Subsequent
+ * read operations will return -1.
+ */
+ private final long contentLength;
+
+ /** The current position */
+ private long pos = 0;
+
+ /** True if the stream is closed. */
+ private boolean closed = false;
+
+ /**
+ * Wrapped input stream that all calls are delegated to.
+ */
+ private SessionInputBuffer in = null;
+
+ /**
+ * Wraps a session input buffer and cuts off output after a defined number
+ * of bytes.
+ *
+ * @param in The session input buffer
+ * @param contentLength The maximum number of bytes that can be read from
+ * the stream. Subsequent read operations will return -1.
+ */
+ public ContentLengthInputStream(final SessionInputBuffer in, final long contentLength) {
+ super();
+ this.in = Args.notNull(in, "Session input buffer");
+ this.contentLength = Args.notNegative(contentLength, "Content length");
+ }
+
+ /**
+ * <p>Reads until the end of the known length of content.</p>
+ *
+ * <p>Does not close the underlying socket input, but instead leaves it
+ * primed to parse the next response.</p>
+ * @throws IOException If an IO problem occurs.
+ */
+ @Override
+ public void close() throws IOException {
+ if (!closed) {
+ try {
+ if (pos < contentLength) {
+ final byte buffer[] = new byte[BUFFER_SIZE];
+ while (read(buffer) >= 0) {
+ }
+ }
+ } finally {
+ // close after above so that we don't throw an exception trying
+ // to read after closed!
+ closed = true;
+ }
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ if (this.in instanceof BufferInfo) {
+ final int len = ((BufferInfo) this.in).length();
+ return Math.min(len, (int) (this.contentLength - this.pos));
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Read the next byte from the stream
+ * @return The next byte or -1 if the end of stream has been reached.
+ * @throws IOException If an IO problem occurs
+ * @see java.io.InputStream#read()
+ */
+ @Override
+ public int read() throws IOException {
+ if (closed) {
+ throw new IOException("Attempted read from closed stream.");
+ }
+
+ if (pos >= contentLength) {
+ return -1;
+ }
+ final int b = this.in.read();
+ if (b == -1) {
+ if (pos < contentLength) {
+ throw new ConnectionClosedException(
+ "Premature end of Content-Length delimited message body (expected: "
+ + contentLength + "; received: " + pos);
+ }
+ } else {
+ pos++;
+ }
+ return b;
+ }
+
+ /**
+ * Does standard {@link InputStream#read(byte[], int, int)} behavior, but
+ * also notifies the watcher when the contents have been consumed.
+ *
+ * @param b The byte array to fill.
+ * @param off Start filling at this position.
+ * @param len The number of bytes to attempt to read.
+ * @return The number of bytes read, or -1 if the end of content has been
+ * reached.
+ *
+ * @throws java.io.IOException Should an error occur on the wrapped stream.
+ */
+ @Override
+ public int read (final byte[] b, final int off, final int len) throws java.io.IOException {
+ if (closed) {
+ throw new IOException("Attempted read from closed stream.");
+ }
+
+ if (pos >= contentLength) {
+ return -1;
+ }
+
+ int chunk = len;
+ if (pos + len > contentLength) {
+ chunk = (int) (contentLength - pos);
+ }
+ final int count = this.in.read(b, off, chunk);
+ if (count == -1 && pos < contentLength) {
+ throw new ConnectionClosedException(
+ "Premature end of Content-Length delimited message body (expected: "
+ + contentLength + "; received: " + pos);
+ }
+ if (count > 0) {
+ pos += count;
+ }
+ return count;
+ }
+
+
+ /**
+ * Read more bytes from the stream.
+ * @param b The byte array to put the new data in.
+ * @return The number of bytes read into the buffer.
+ * @throws IOException If an IO problem occurs
+ * @see java.io.InputStream#read(byte[])
+ */
+ @Override
+ public int read(final byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Skips and discards a number of bytes from the input stream.
+ * @param n The number of bytes to skip.
+ * @return The actual number of bytes skipped. <= 0 if no bytes
+ * are skipped.
+ * @throws IOException If an error occurs while skipping bytes.
+ * @see InputStream#skip(long)
+ */
+ @Override
+ public long skip(final long n) throws IOException {
+ if (n <= 0) {
+ return 0;
+ }
+ final byte[] buffer = new byte[BUFFER_SIZE];
+ // make sure we don't skip more bytes than are
+ // still available
+ long remaining = Math.min(n, this.contentLength - this.pos);
+ // skip and keep track of the bytes actually skipped
+ long count = 0;
+ while (remaining > 0) {
+ final int l = read(buffer, 0, (int)Math.min(BUFFER_SIZE, remaining));
+ if (l == -1) {
+ break;
+ }
+ count += l;
+ remaining -= l;
+ }
+ return count;
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthOutputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthOutputStream.java
new file mode 100644
index 000000000..1c4e588d0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/ContentLengthOutputStream.java
@@ -0,0 +1,136 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Output stream that cuts off after a defined number of bytes. This class
+ * is used to send content of HTTP messages where the end of the content entity
+ * is determined by the value of the <code>Content-Length header</code>.
+ * Entities transferred using this stream can be maximum {@link Long#MAX_VALUE}
+ * long.
+ * <p>
+ * Note that this class NEVER closes the underlying stream, even when close
+ * gets called. Instead, the stream will be marked as closed and no further
+ * output will be permitted.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class ContentLengthOutputStream extends OutputStream {
+
+ /**
+ * Wrapped session output buffer.
+ */
+ private final SessionOutputBuffer out;
+
+ /**
+ * The maximum number of bytes that can be written the stream. Subsequent
+ * write operations will be ignored.
+ */
+ private final long contentLength;
+
+ /** Total bytes written */
+ private long total = 0;
+
+ /** True if the stream is closed. */
+ private boolean closed = false;
+
+ /**
+ * Wraps a session output buffer and cuts off output after a defined number
+ * of bytes.
+ *
+ * @param out The session output buffer
+ * @param contentLength The maximum number of bytes that can be written to
+ * the stream. Subsequent write operations will be ignored.
+ *
+ * @since 4.0
+ */
+ public ContentLengthOutputStream(final SessionOutputBuffer out, final long contentLength) {
+ super();
+ this.out = Args.notNull(out, "Session output buffer");
+ this.contentLength = Args.notNegative(contentLength, "Content length");
+ }
+
+ /**
+ * <p>Does not close the underlying socket output.</p>
+ *
+ * @throws IOException If an I/O problem occurs.
+ */
+ @Override
+ public void close() throws IOException {
+ if (!this.closed) {
+ this.closed = true;
+ this.out.flush();
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ this.out.flush();
+ }
+
+ @Override
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ if (this.closed) {
+ throw new IOException("Attempted write to closed stream.");
+ }
+ if (this.total < this.contentLength) {
+ final long max = this.contentLength - this.total;
+ int chunk = len;
+ if (chunk > max) {
+ chunk = (int) max;
+ }
+ this.out.write(b, off, chunk);
+ this.total += chunk;
+ }
+ }
+
+ @Override
+ public void write(final byte[] b) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ @Override
+ public void write(final int b) throws IOException {
+ if (this.closed) {
+ throw new IOException("Attempted write to closed stream.");
+ }
+ if (this.total < this.contentLength) {
+ this.out.write(b);
+ this.total++;
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParser.java
new file mode 100644
index 000000000..70383a22e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParser.java
@@ -0,0 +1,140 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.ConnectionClosedException;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestFactory;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.impl.DefaultHttpRequestFactory;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.LineParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * HTTP request parser that obtain its input from an instance
+ * of {@link SessionInputBuffer}.
+ *
+ * @since 4.2
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public class DefaultHttpRequestParser extends AbstractMessageParser<HttpRequest> {
+
+ private final HttpRequestFactory requestFactory;
+ private final CharArrayBuffer lineBuf;
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param buffer the session input buffer.
+ * @param lineParser the line parser.
+ * @param requestFactory the factory to use to create
+ * {@link HttpRequest}s.
+ * @param params HTTP parameters.
+ *
+ * @deprecated (4.3) use
+ * {@link DefaultHttpRequestParser#DefaultHttpRequestParser(SessionInputBuffer, LineParser,
+ * HttpRequestFactory, MessageConstraints)}
+ */
+ @Deprecated
+ public DefaultHttpRequestParser(
+ final SessionInputBuffer buffer,
+ final LineParser lineParser,
+ final HttpRequestFactory requestFactory,
+ final HttpParams params) {
+ super(buffer, lineParser, params);
+ this.requestFactory = Args.notNull(requestFactory, "Request factory");
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ /**
+ * Creates new instance of DefaultHttpRequestParser.
+ *
+ * @param buffer the session input buffer.
+ * @param lineParser the line parser. If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.message.BasicLineParser#INSTANCE} will be used.
+ * @param requestFactory the response factory. If <code>null</code>
+ * {@link DefaultHttpRequestFactory#INSTANCE} will be used.
+ * @param constraints the message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ *
+ * @since 4.3
+ */
+ public DefaultHttpRequestParser(
+ final SessionInputBuffer buffer,
+ final LineParser lineParser,
+ final HttpRequestFactory requestFactory,
+ final MessageConstraints constraints) {
+ super(buffer, lineParser, constraints);
+ this.requestFactory = requestFactory != null ? requestFactory :
+ DefaultHttpRequestFactory.INSTANCE;
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public DefaultHttpRequestParser(
+ final SessionInputBuffer buffer,
+ final MessageConstraints constraints) {
+ this(buffer, null, null, constraints);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public DefaultHttpRequestParser(final SessionInputBuffer buffer) {
+ this(buffer, null, null, MessageConstraints.DEFAULT);
+ }
+
+ @Override
+ protected HttpRequest parseHead(
+ final SessionInputBuffer sessionBuffer)
+ throws IOException, HttpException, ParseException {
+
+ this.lineBuf.clear();
+ final int i = sessionBuffer.readLine(this.lineBuf);
+ if (i == -1) {
+ throw new ConnectionClosedException("Client closed connection");
+ }
+ final ParserCursor cursor = new ParserCursor(0, this.lineBuf.length());
+ final RequestLine requestline = this.lineParser.parseRequestLine(this.lineBuf, cursor);
+ return this.requestFactory.newHttpRequest(requestline);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParserFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParserFactory.java
new file mode 100644
index 000000000..81e886059
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestParserFactory.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestFactory;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.impl.DefaultHttpRequestFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.BasicLineParser;
+import ch.boye.httpclientandroidlib.message.LineParser;
+
+/**
+ * Default factory for request message parsers.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultHttpRequestParserFactory implements HttpMessageParserFactory<HttpRequest> {
+
+ public static final DefaultHttpRequestParserFactory INSTANCE = new DefaultHttpRequestParserFactory();
+
+ private final LineParser lineParser;
+ private final HttpRequestFactory requestFactory;
+
+ public DefaultHttpRequestParserFactory(final LineParser lineParser,
+ final HttpRequestFactory requestFactory) {
+ super();
+ this.lineParser = lineParser != null ? lineParser : BasicLineParser.INSTANCE;
+ this.requestFactory = requestFactory != null ? requestFactory
+ : DefaultHttpRequestFactory.INSTANCE;
+ }
+
+ public DefaultHttpRequestParserFactory() {
+ this(null, null);
+ }
+
+ public HttpMessageParser<HttpRequest> create(final SessionInputBuffer buffer,
+ final MessageConstraints constraints) {
+ return new DefaultHttpRequestParser(buffer, lineParser, requestFactory, constraints);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriter.java
new file mode 100644
index 000000000..0f3b31e18
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriter.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.message.LineFormatter;
+
+/**
+ * HTTP request writer that serializes its output to an instance of {@link SessionOutputBuffer}.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class DefaultHttpRequestWriter extends AbstractMessageWriter<HttpRequest> {
+
+ /**
+ * Creates an instance of DefaultHttpRequestWriter.
+ *
+ * @param buffer the session output buffer.
+ * @param formatter the line formatter If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.message.BasicLineFormatter#INSTANCE}
+ * will be used.
+ */
+ public DefaultHttpRequestWriter(
+ final SessionOutputBuffer buffer,
+ final LineFormatter formatter) {
+ super(buffer, formatter);
+ }
+
+ public DefaultHttpRequestWriter(final SessionOutputBuffer buffer) {
+ this(buffer, null);
+ }
+
+ @Override
+ protected void writeHeadLine(final HttpRequest message) throws IOException {
+ lineFormatter.formatRequestLine(this.lineBuf, message.getRequestLine());
+ this.sessionBuffer.writeLine(this.lineBuf);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriterFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriterFactory.java
new file mode 100644
index 000000000..410cc2ac3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpRequestWriterFactory.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriter;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.message.BasicLineFormatter;
+import ch.boye.httpclientandroidlib.message.LineFormatter;
+
+/**
+ * Default factory for request message writers.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultHttpRequestWriterFactory implements HttpMessageWriterFactory<HttpRequest> {
+
+ public static final DefaultHttpRequestWriterFactory INSTANCE = new DefaultHttpRequestWriterFactory();
+
+ private final LineFormatter lineFormatter;
+
+ public DefaultHttpRequestWriterFactory(final LineFormatter lineFormatter) {
+ super();
+ this.lineFormatter = lineFormatter != null ? lineFormatter : BasicLineFormatter.INSTANCE;
+ }
+
+ public DefaultHttpRequestWriterFactory() {
+ this(null);
+ }
+
+ public HttpMessageWriter<HttpRequest> create(final SessionOutputBuffer buffer) {
+ return new DefaultHttpRequestWriter(buffer, lineFormatter);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParser.java
new file mode 100644
index 000000000..a8428e812
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParser.java
@@ -0,0 +1,141 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.NoHttpResponseException;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.impl.DefaultHttpResponseFactory;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.LineParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * HTTP response parser that obtain its input from an instance
+ * of {@link SessionInputBuffer}.
+ *
+ * @since 4.2
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public class DefaultHttpResponseParser extends AbstractMessageParser<HttpResponse> {
+
+ private final HttpResponseFactory responseFactory;
+ private final CharArrayBuffer lineBuf;
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param buffer the session input buffer.
+ * @param lineParser the line parser.
+ * @param responseFactory the factory to use to create
+ * {@link HttpResponse}s.
+ * @param params HTTP parameters.
+ *
+ * @deprecated (4.3) use
+ * {@link DefaultHttpResponseParser#DefaultHttpResponseParser(SessionInputBuffer, LineParser,
+ * HttpResponseFactory, MessageConstraints)}
+ */
+ @Deprecated
+ public DefaultHttpResponseParser(
+ final SessionInputBuffer buffer,
+ final LineParser lineParser,
+ final HttpResponseFactory responseFactory,
+ final HttpParams params) {
+ super(buffer, lineParser, params);
+ this.responseFactory = Args.notNull(responseFactory, "Response factory");
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ /**
+ * Creates new instance of DefaultHttpResponseParser.
+ *
+ * @param buffer the session input buffer.
+ * @param lineParser the line parser. If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.message.BasicLineParser#INSTANCE} will be used
+ * @param responseFactory the response factory. If <code>null</code>
+ * {@link DefaultHttpResponseFactory#INSTANCE} will be used.
+ * @param constraints the message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ *
+ * @since 4.3
+ */
+ public DefaultHttpResponseParser(
+ final SessionInputBuffer buffer,
+ final LineParser lineParser,
+ final HttpResponseFactory responseFactory,
+ final MessageConstraints constraints) {
+ super(buffer, lineParser, constraints);
+ this.responseFactory = responseFactory != null ? responseFactory :
+ DefaultHttpResponseFactory.INSTANCE;
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public DefaultHttpResponseParser(
+ final SessionInputBuffer buffer,
+ final MessageConstraints constraints) {
+ this(buffer, null, null, constraints);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public DefaultHttpResponseParser(final SessionInputBuffer buffer) {
+ this(buffer, null, null, MessageConstraints.DEFAULT);
+ }
+
+ @Override
+ protected HttpResponse parseHead(
+ final SessionInputBuffer sessionBuffer)
+ throws IOException, HttpException, ParseException {
+
+ this.lineBuf.clear();
+ final int i = sessionBuffer.readLine(this.lineBuf);
+ if (i == -1) {
+ throw new NoHttpResponseException("The target server failed to respond");
+ }
+ //create the status line from the status string
+ final ParserCursor cursor = new ParserCursor(0, this.lineBuf.length());
+ final StatusLine statusline = lineParser.parseStatusLine(this.lineBuf, cursor);
+ return this.responseFactory.newHttpResponse(statusline, null);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParserFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParserFactory.java
new file mode 100644
index 000000000..318abcf70
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseParserFactory.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.impl.DefaultHttpResponseFactory;
+import ch.boye.httpclientandroidlib.io.HttpMessageParser;
+import ch.boye.httpclientandroidlib.io.HttpMessageParserFactory;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.BasicLineParser;
+import ch.boye.httpclientandroidlib.message.LineParser;
+
+/**
+ * Default factory for response message parsers.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultHttpResponseParserFactory implements HttpMessageParserFactory<HttpResponse> {
+
+ public static final DefaultHttpResponseParserFactory INSTANCE = new DefaultHttpResponseParserFactory();
+
+ private final LineParser lineParser;
+ private final HttpResponseFactory responseFactory;
+
+ public DefaultHttpResponseParserFactory(final LineParser lineParser,
+ final HttpResponseFactory responseFactory) {
+ super();
+ this.lineParser = lineParser != null ? lineParser : BasicLineParser.INSTANCE;
+ this.responseFactory = responseFactory != null ? responseFactory
+ : DefaultHttpResponseFactory.INSTANCE;
+ }
+
+ public DefaultHttpResponseParserFactory() {
+ this(null, null);
+ }
+
+ public HttpMessageParser<HttpResponse> create(final SessionInputBuffer buffer,
+ final MessageConstraints constraints) {
+ return new DefaultHttpResponseParser(buffer, lineParser, responseFactory, constraints);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriter.java
new file mode 100644
index 000000000..8cdef00a5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriter.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.message.LineFormatter;
+
+/**
+ * HTTP response writer that serializes its output to an instance of {@link SessionOutputBuffer}.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class DefaultHttpResponseWriter extends AbstractMessageWriter<HttpResponse> {
+
+ /**
+ * Creates an instance of DefaultHttpResponseWriter.
+ *
+ * @param buffer the session output buffer.
+ * @param formatter the line formatter If <code>null</code>
+ * {@link ch.boye.httpclientandroidlib.message.BasicLineFormatter#INSTANCE}
+ * will be used.
+ */
+ public DefaultHttpResponseWriter(
+ final SessionOutputBuffer buffer,
+ final LineFormatter formatter) {
+ super(buffer, formatter);
+ }
+
+ public DefaultHttpResponseWriter(final SessionOutputBuffer buffer) {
+ super(buffer, null);
+ }
+
+ @Override
+ protected void writeHeadLine(final HttpResponse message) throws IOException {
+ lineFormatter.formatStatusLine(this.lineBuf, message.getStatusLine());
+ this.sessionBuffer.writeLine(this.lineBuf);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriterFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriterFactory.java
new file mode 100644
index 000000000..9dc29606d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/DefaultHttpResponseWriterFactory.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriter;
+import ch.boye.httpclientandroidlib.io.HttpMessageWriterFactory;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.message.BasicLineFormatter;
+import ch.boye.httpclientandroidlib.message.LineFormatter;
+
+/**
+ * Default factory for response message writers.
+ *
+ * @since 4.3
+ */
+@Immutable
+public class DefaultHttpResponseWriterFactory implements HttpMessageWriterFactory<HttpResponse> {
+
+ public static final DefaultHttpResponseWriterFactory INSTANCE = new DefaultHttpResponseWriterFactory();
+
+ private final LineFormatter lineFormatter;
+
+ public DefaultHttpResponseWriterFactory(final LineFormatter lineFormatter) {
+ super();
+ this.lineFormatter = lineFormatter != null ? lineFormatter : BasicLineFormatter.INSTANCE;
+ }
+
+ public DefaultHttpResponseWriterFactory() {
+ this(null);
+ }
+
+ public HttpMessageWriter<HttpResponse> create(final SessionOutputBuffer buffer) {
+ return new DefaultHttpResponseWriter(buffer, lineFormatter);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestParser.java
new file mode 100644
index 000000000..9c68b6938
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestParser.java
@@ -0,0 +1,102 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.ConnectionClosedException;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.HttpRequestFactory;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.LineParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * HTTP request parser that obtain its input from an instance
+ * of {@link SessionInputBuffer}.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link DefaultHttpRequestParser}
+ */
+@Deprecated
+@NotThreadSafe
+public class HttpRequestParser extends AbstractMessageParser<HttpMessage> {
+
+ private final HttpRequestFactory requestFactory;
+ private final CharArrayBuffer lineBuf;
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param buffer the session input buffer.
+ * @param parser the line parser.
+ * @param requestFactory the factory to use to create
+ * {@link ch.boye.httpclientandroidlib.HttpRequest}s.
+ * @param params HTTP parameters.
+ */
+ public HttpRequestParser(
+ final SessionInputBuffer buffer,
+ final LineParser parser,
+ final HttpRequestFactory requestFactory,
+ final HttpParams params) {
+ super(buffer, parser, params);
+ this.requestFactory = Args.notNull(requestFactory, "Request factory");
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ @Override
+ protected HttpMessage parseHead(
+ final SessionInputBuffer sessionBuffer)
+ throws IOException, HttpException, ParseException {
+
+ this.lineBuf.clear();
+ final int i = sessionBuffer.readLine(this.lineBuf);
+ if (i == -1) {
+ throw new ConnectionClosedException("Client closed connection");
+ }
+ final ParserCursor cursor = new ParserCursor(0, this.lineBuf.length());
+ final RequestLine requestline = this.lineParser.parseRequestLine(this.lineBuf, cursor);
+ return this.requestFactory.newHttpRequest(requestline);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestWriter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestWriter.java
new file mode 100644
index 000000000..3603ef573
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpRequestWriter.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.message.LineFormatter;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * HTTP request writer that serializes its output to an instance
+ * of {@link SessionOutputBuffer}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultHttpRequestWriter}
+ */
+@NotThreadSafe
+@Deprecated
+public class HttpRequestWriter extends AbstractMessageWriter<HttpRequest> {
+
+ public HttpRequestWriter(final SessionOutputBuffer buffer,
+ final LineFormatter formatter,
+ final HttpParams params) {
+ super(buffer, formatter, params);
+ }
+
+ @Override
+ protected void writeHeadLine(final HttpRequest message) throws IOException {
+ lineFormatter.formatRequestLine(this.lineBuf, message.getRequestLine());
+ this.sessionBuffer.writeLine(this.lineBuf);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseParser.java
new file mode 100644
index 000000000..a94eae36c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseParser.java
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.NoHttpResponseException;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.message.LineParser;
+import ch.boye.httpclientandroidlib.message.ParserCursor;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * HTTP response parser that obtain its input from an instance
+ * of {@link SessionInputBuffer}.
+ * <p>
+ * The following parameters can be used to customize the behavior of this
+ * class:
+ * <ul>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
+ * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ * </ul>
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) use {@link DefaultHttpResponseParser}
+ */
+@Deprecated
+@NotThreadSafe
+public class HttpResponseParser extends AbstractMessageParser<HttpMessage> {
+
+ private final HttpResponseFactory responseFactory;
+ private final CharArrayBuffer lineBuf;
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param buffer the session input buffer.
+ * @param parser the line parser.
+ * @param responseFactory the factory to use to create
+ * {@link ch.boye.httpclientandroidlib.HttpResponse}s.
+ * @param params HTTP parameters.
+ */
+ public HttpResponseParser(
+ final SessionInputBuffer buffer,
+ final LineParser parser,
+ final HttpResponseFactory responseFactory,
+ final HttpParams params) {
+ super(buffer, parser, params);
+ this.responseFactory = Args.notNull(responseFactory, "Response factory");
+ this.lineBuf = new CharArrayBuffer(128);
+ }
+
+ @Override
+ protected HttpMessage parseHead(
+ final SessionInputBuffer sessionBuffer)
+ throws IOException, HttpException, ParseException {
+
+ this.lineBuf.clear();
+ final int i = sessionBuffer.readLine(this.lineBuf);
+ if (i == -1) {
+ throw new NoHttpResponseException("The target server failed to respond");
+ }
+ //create the status line from the status string
+ final ParserCursor cursor = new ParserCursor(0, this.lineBuf.length());
+ final StatusLine statusline = lineParser.parseStatusLine(this.lineBuf, cursor);
+ return this.responseFactory.newHttpResponse(statusline, null);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseWriter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseWriter.java
new file mode 100644
index 000000000..2e82ade18
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpResponseWriter.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.message.LineFormatter;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+
+/**
+ * HTTP response writer that serializes its output to an instance
+ * of {@link SessionOutputBuffer}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link DefaultHttpResponseWriter}
+ */
+@NotThreadSafe
+@Deprecated
+public class HttpResponseWriter extends AbstractMessageWriter<HttpResponse> {
+
+ public HttpResponseWriter(final SessionOutputBuffer buffer,
+ final LineFormatter formatter,
+ final HttpParams params) {
+ super(buffer, formatter, params);
+ }
+
+ @Override
+ protected void writeHeadLine(final HttpResponse message) throws IOException {
+ lineFormatter.formatStatusLine(this.lineBuf, message.getStatusLine());
+ this.sessionBuffer.writeLine(this.lineBuf);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java
new file mode 100644
index 000000000..8bd4eae5f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+
+/**
+ * Default implementation of {@link HttpTransportMetrics}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HttpTransportMetricsImpl implements HttpTransportMetrics {
+
+ private long bytesTransferred = 0;
+
+ public HttpTransportMetricsImpl() {
+ super();
+ }
+
+ public long getBytesTransferred() {
+ return this.bytesTransferred;
+ }
+
+ public void setBytesTransferred(final long count) {
+ this.bytesTransferred = count;
+ }
+
+ public void incrementBytesTransferred(final long count) {
+ this.bytesTransferred += count;
+ }
+
+ public void reset() {
+ this.bytesTransferred = 0;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityInputStream.java
new file mode 100644
index 000000000..98e1cf81a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityInputStream.java
@@ -0,0 +1,99 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.BufferInfo;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Input stream that reads data without any transformation. The end of the
+ * content entity is demarcated by closing the underlying connection
+ * (EOF condition). Entities transferred using this input stream can be of
+ * unlimited length.
+ * <p>
+ * Note that this class NEVER closes the underlying stream, even when close
+ * gets called. Instead, it will read until the end of the stream (until
+ * <code>-1</code> is returned).
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class IdentityInputStream extends InputStream {
+
+ private final SessionInputBuffer in;
+
+ private boolean closed = false;
+
+ /**
+ * Wraps session input stream and reads input until the the end of stream.
+ *
+ * @param in The session input buffer
+ */
+ public IdentityInputStream(final SessionInputBuffer in) {
+ super();
+ this.in = Args.notNull(in, "Session input buffer");
+ }
+
+ @Override
+ public int available() throws IOException {
+ if (this.in instanceof BufferInfo) {
+ return ((BufferInfo) this.in).length();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ this.closed = true;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (this.closed) {
+ return -1;
+ } else {
+ return this.in.read();
+ }
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ if (this.closed) {
+ return -1;
+ } else {
+ return this.in.read(b, off, len);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityOutputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityOutputStream.java
new file mode 100644
index 000000000..ac2f613b7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/IdentityOutputStream.java
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Output stream that writes data without any transformation. The end of
+ * the content entity is demarcated by closing the underlying connection
+ * (EOF condition). Entities transferred using this input stream can be of
+ * unlimited length.
+ * <p>
+ * Note that this class NEVER closes the underlying stream, even when close
+ * gets called. Instead, the stream will be marked as closed and no further
+ * output will be permitted.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class IdentityOutputStream extends OutputStream {
+
+ /**
+ * Wrapped session output buffer.
+ */
+ private final SessionOutputBuffer out;
+
+ /** True if the stream is closed. */
+ private boolean closed = false;
+
+ public IdentityOutputStream(final SessionOutputBuffer out) {
+ super();
+ this.out = Args.notNull(out, "Session output buffer");
+ }
+
+ /**
+ * <p>Does not close the underlying socket output.</p>
+ *
+ * @throws IOException If an I/O problem occurs.
+ */
+ @Override
+ public void close() throws IOException {
+ if (!this.closed) {
+ this.closed = true;
+ this.out.flush();
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ this.out.flush();
+ }
+
+ @Override
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ if (this.closed) {
+ throw new IOException("Attempted write to closed stream.");
+ }
+ this.out.write(b, off, len);
+ }
+
+ @Override
+ public void write(final byte[] b) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ @Override
+ public void write(final int b) throws IOException {
+ if (this.closed) {
+ throw new IOException("Attempted write to closed stream.");
+ }
+ this.out.write(b);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionInputBufferImpl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionInputBufferImpl.java
new file mode 100644
index 000000000..ed86cb94b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionInputBufferImpl.java
@@ -0,0 +1,399 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+
+import ch.boye.httpclientandroidlib.MessageConstraintException;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.io.BufferInfo;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.ByteArrayBuffer;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract base class for session input buffers that stream data from
+ * an arbitrary {@link InputStream}. This class buffers input data in
+ * an internal byte array for optimal input performance.
+ * <p/>
+ * {@link #readLine(CharArrayBuffer)} and {@link #readLine()} methods of this
+ * class treat a lone LF as valid line delimiters in addition to CR-LF required
+ * by the HTTP specification.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class SessionInputBufferImpl implements SessionInputBuffer, BufferInfo {
+
+ private final HttpTransportMetricsImpl metrics;
+ private final byte[] buffer;
+ private final ByteArrayBuffer linebuffer;
+ private final int minChunkLimit;
+ private final MessageConstraints constraints;
+ private final CharsetDecoder decoder;
+
+ private InputStream instream;
+ private int bufferpos;
+ private int bufferlen;
+ private CharBuffer cbuf;
+
+ /**
+ * Creates new instance of SessionInputBufferImpl.
+ *
+ * @param metrics HTTP transport metrics.
+ * @param buffersize buffer size. Must be a positive number.
+ * @param minChunkLimit size limit below which data chunks should be buffered in memory
+ * in order to minimize native method invocations on the underlying network socket.
+ * The optimal value of this parameter can be platform specific and defines a trade-off
+ * between performance of memory copy operations and that of native method invocation.
+ * If negative default chunk limited will be used.
+ * @param constraints Message constraints. If <code>null</code>
+ * {@link MessageConstraints#DEFAULT} will be used.
+ * @param chardecoder chardecoder to be used for decoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for byte to char conversion.
+ */
+ public SessionInputBufferImpl(
+ final HttpTransportMetricsImpl metrics,
+ final int buffersize,
+ final int minChunkLimit,
+ final MessageConstraints constraints,
+ final CharsetDecoder chardecoder) {
+ Args.notNull(metrics, "HTTP transport metrcis");
+ Args.positive(buffersize, "Buffer size");
+ this.metrics = metrics;
+ this.buffer = new byte[buffersize];
+ this.bufferpos = 0;
+ this.bufferlen = 0;
+ this.minChunkLimit = minChunkLimit >= 0 ? minChunkLimit : 512;
+ this.constraints = constraints != null ? constraints : MessageConstraints.DEFAULT;
+ this.linebuffer = new ByteArrayBuffer(buffersize);
+ this.decoder = chardecoder;
+ }
+
+ public SessionInputBufferImpl(
+ final HttpTransportMetricsImpl metrics,
+ final int buffersize) {
+ this(metrics, buffersize, buffersize, null, null);
+ }
+
+ public void bind(final InputStream instream) {
+ this.instream = instream;
+ }
+
+ public boolean isBound() {
+ return this.instream != null;
+ }
+
+ public int capacity() {
+ return this.buffer.length;
+ }
+
+ public int length() {
+ return this.bufferlen - this.bufferpos;
+ }
+
+ public int available() {
+ return capacity() - length();
+ }
+
+ private int streamRead(final byte[] b, final int off, final int len) throws IOException {
+ Asserts.notNull(this.instream, "Input stream");
+ return this.instream.read(b, off, len);
+ }
+
+ public int fillBuffer() throws IOException {
+ // compact the buffer if necessary
+ if (this.bufferpos > 0) {
+ final int len = this.bufferlen - this.bufferpos;
+ if (len > 0) {
+ System.arraycopy(this.buffer, this.bufferpos, this.buffer, 0, len);
+ }
+ this.bufferpos = 0;
+ this.bufferlen = len;
+ }
+ final int l;
+ final int off = this.bufferlen;
+ final int len = this.buffer.length - off;
+ l = streamRead(this.buffer, off, len);
+ if (l == -1) {
+ return -1;
+ } else {
+ this.bufferlen = off + l;
+ this.metrics.incrementBytesTransferred(l);
+ return l;
+ }
+ }
+
+ public boolean hasBufferedData() {
+ return this.bufferpos < this.bufferlen;
+ }
+
+ public void clear() {
+ this.bufferpos = 0;
+ this.bufferlen = 0;
+ }
+
+ public int read() throws IOException {
+ int noRead;
+ while (!hasBufferedData()) {
+ noRead = fillBuffer();
+ if (noRead == -1) {
+ return -1;
+ }
+ }
+ return this.buffer[this.bufferpos++] & 0xff;
+ }
+
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ if (b == null) {
+ return 0;
+ }
+ if (hasBufferedData()) {
+ final int chunk = Math.min(len, this.bufferlen - this.bufferpos);
+ System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
+ this.bufferpos += chunk;
+ return chunk;
+ }
+ // If the remaining capacity is big enough, read directly from the
+ // underlying input stream bypassing the buffer.
+ if (len > this.minChunkLimit) {
+ final int read = streamRead(b, off, len);
+ if (read > 0) {
+ this.metrics.incrementBytesTransferred(read);
+ }
+ return read;
+ } else {
+ // otherwise read to the buffer first
+ while (!hasBufferedData()) {
+ final int noRead = fillBuffer();
+ if (noRead == -1) {
+ return -1;
+ }
+ }
+ final int chunk = Math.min(len, this.bufferlen - this.bufferpos);
+ System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
+ this.bufferpos += chunk;
+ return chunk;
+ }
+ }
+
+ public int read(final byte[] b) throws IOException {
+ if (b == null) {
+ return 0;
+ }
+ return read(b, 0, b.length);
+ }
+
+ private int locateLF() {
+ for (int i = this.bufferpos; i < this.bufferlen; i++) {
+ if (this.buffer[i] == HTTP.LF) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Reads a complete line of characters up to a line delimiter from this
+ * session buffer into the given line buffer. The number of chars actually
+ * read is returned as an integer. The line delimiter itself is discarded.
+ * If no char is available because the end of the stream has been reached,
+ * the value <code>-1</code> is returned. This method blocks until input
+ * data is available, end of file is detected, or an exception is thrown.
+ * <p>
+ * This method treats a lone LF as a valid line delimiters in addition
+ * to CR-LF required by the HTTP specification.
+ *
+ * @param charbuffer the line buffer.
+ * @return one line of characters
+ * @exception IOException if an I/O error occurs.
+ */
+ public int readLine(final CharArrayBuffer charbuffer) throws IOException {
+ Args.notNull(charbuffer, "Char array buffer");
+ int noRead = 0;
+ boolean retry = true;
+ while (retry) {
+ // attempt to find end of line (LF)
+ final int i = locateLF();
+ if (i != -1) {
+ // end of line found.
+ if (this.linebuffer.isEmpty()) {
+ // the entire line is preset in the read buffer
+ return lineFromReadBuffer(charbuffer, i);
+ }
+ retry = false;
+ final int len = i + 1 - this.bufferpos;
+ this.linebuffer.append(this.buffer, this.bufferpos, len);
+ this.bufferpos = i + 1;
+ } else {
+ // end of line not found
+ if (hasBufferedData()) {
+ final int len = this.bufferlen - this.bufferpos;
+ this.linebuffer.append(this.buffer, this.bufferpos, len);
+ this.bufferpos = this.bufferlen;
+ }
+ noRead = fillBuffer();
+ if (noRead == -1) {
+ retry = false;
+ }
+ }
+ final int maxLineLen = this.constraints.getMaxLineLength();
+ if (maxLineLen > 0 && this.linebuffer.length() >= maxLineLen) {
+ throw new MessageConstraintException("Maximum line length limit exceeded");
+ }
+ }
+ if (noRead == -1 && this.linebuffer.isEmpty()) {
+ // indicate the end of stream
+ return -1;
+ }
+ return lineFromLineBuffer(charbuffer);
+ }
+
+ /**
+ * Reads a complete line of characters up to a line delimiter from this
+ * session buffer. The line delimiter itself is discarded. If no char is
+ * available because the end of the stream has been reached,
+ * <code>null</code> is returned. This method blocks until input data is
+ * available, end of file is detected, or an exception is thrown.
+ * <p>
+ * This method treats a lone LF as a valid line delimiters in addition
+ * to CR-LF required by the HTTP specification.
+ *
+ * @return HTTP line as a string
+ * @exception IOException if an I/O error occurs.
+ */
+ private int lineFromLineBuffer(final CharArrayBuffer charbuffer)
+ throws IOException {
+ // discard LF if found
+ int len = this.linebuffer.length();
+ if (len > 0) {
+ if (this.linebuffer.byteAt(len - 1) == HTTP.LF) {
+ len--;
+ }
+ // discard CR if found
+ if (len > 0) {
+ if (this.linebuffer.byteAt(len - 1) == HTTP.CR) {
+ len--;
+ }
+ }
+ }
+ if (this.decoder == null) {
+ charbuffer.append(this.linebuffer, 0, len);
+ } else {
+ final ByteBuffer bbuf = ByteBuffer.wrap(this.linebuffer.buffer(), 0, len);
+ len = appendDecoded(charbuffer, bbuf);
+ }
+ this.linebuffer.clear();
+ return len;
+ }
+
+ private int lineFromReadBuffer(final CharArrayBuffer charbuffer, final int position)
+ throws IOException {
+ int pos = position;
+ final int off = this.bufferpos;
+ int len;
+ this.bufferpos = pos + 1;
+ if (pos > off && this.buffer[pos - 1] == HTTP.CR) {
+ // skip CR if found
+ pos--;
+ }
+ len = pos - off;
+ if (this.decoder == null) {
+ charbuffer.append(this.buffer, off, len);
+ } else {
+ final ByteBuffer bbuf = ByteBuffer.wrap(this.buffer, off, len);
+ len = appendDecoded(charbuffer, bbuf);
+ }
+ return len;
+ }
+
+ private int appendDecoded(
+ final CharArrayBuffer charbuffer, final ByteBuffer bbuf) throws IOException {
+ if (!bbuf.hasRemaining()) {
+ return 0;
+ }
+ if (this.cbuf == null) {
+ this.cbuf = CharBuffer.allocate(1024);
+ }
+ this.decoder.reset();
+ int len = 0;
+ while (bbuf.hasRemaining()) {
+ final CoderResult result = this.decoder.decode(bbuf, this.cbuf, true);
+ len += handleDecodingResult(result, charbuffer, bbuf);
+ }
+ final CoderResult result = this.decoder.flush(this.cbuf);
+ len += handleDecodingResult(result, charbuffer, bbuf);
+ this.cbuf.clear();
+ return len;
+ }
+
+ private int handleDecodingResult(
+ final CoderResult result,
+ final CharArrayBuffer charbuffer,
+ final ByteBuffer bbuf) throws IOException {
+ if (result.isError()) {
+ result.throwException();
+ }
+ this.cbuf.flip();
+ final int len = this.cbuf.remaining();
+ while (this.cbuf.hasRemaining()) {
+ charbuffer.append(this.cbuf.get());
+ }
+ this.cbuf.compact();
+ return len;
+ }
+
+ public String readLine() throws IOException {
+ final CharArrayBuffer charbuffer = new CharArrayBuffer(64);
+ final int l = readLine(charbuffer);
+ if (l != -1) {
+ return charbuffer.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public boolean isDataAvailable(final int timeout) throws IOException {
+ return hasBufferedData();
+ }
+
+ public HttpTransportMetrics getMetrics() {
+ return this.metrics;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionOutputBufferImpl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionOutputBufferImpl.java
new file mode 100644
index 000000000..99ca871ce
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SessionOutputBufferImpl.java
@@ -0,0 +1,283 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.BufferInfo;
+import ch.boye.httpclientandroidlib.io.HttpTransportMetrics;
+import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+import ch.boye.httpclientandroidlib.util.ByteArrayBuffer;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Abstract base class for session output buffers that stream data to
+ * an arbitrary {@link OutputStream}. This class buffers small chunks of
+ * output data in an internal byte array for optimal output performance.
+ * </p>
+ * {@link #writeLine(CharArrayBuffer)} and {@link #writeLine(String)} methods
+ * of this class use CR-LF as a line delimiter.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class SessionOutputBufferImpl implements SessionOutputBuffer, BufferInfo {
+
+ private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
+
+ private final HttpTransportMetricsImpl metrics;
+ private final ByteArrayBuffer buffer;
+ private final int fragementSizeHint;
+ private final CharsetEncoder encoder;
+
+ private OutputStream outstream;
+ private ByteBuffer bbuf;
+
+ /**
+ * Creates new instance of SessionOutputBufferImpl.
+ *
+ * @param metrics HTTP transport metrics.
+ * @param buffersize buffer size. Must be a positive number.
+ * @param fragementSizeHint fragment size hint defining a minimal size of a fragment
+ * that should be written out directly to the socket bypassing the session buffer.
+ * Value <code>0</code> disables fragment buffering.
+ * @param charencoder charencoder to be used for encoding HTTP protocol elements.
+ * If <code>null</code> simple type cast will be used for char to byte conversion.
+ */
+ public SessionOutputBufferImpl(
+ final HttpTransportMetricsImpl metrics,
+ final int buffersize,
+ final int fragementSizeHint,
+ final CharsetEncoder charencoder) {
+ super();
+ Args.positive(buffersize, "Buffer size");
+ Args.notNull(metrics, "HTTP transport metrcis");
+ this.metrics = metrics;
+ this.buffer = new ByteArrayBuffer(buffersize);
+ this.fragementSizeHint = fragementSizeHint >= 0 ? fragementSizeHint : 0;
+ this.encoder = charencoder;
+ }
+
+ public SessionOutputBufferImpl(
+ final HttpTransportMetricsImpl metrics,
+ final int buffersize) {
+ this(metrics, buffersize, buffersize, null);
+ }
+
+ public void bind(final OutputStream outstream) {
+ this.outstream = outstream;
+ }
+
+ public boolean isBound() {
+ return this.outstream != null;
+ }
+
+ public int capacity() {
+ return this.buffer.capacity();
+ }
+
+ public int length() {
+ return this.buffer.length();
+ }
+
+ public int available() {
+ return capacity() - length();
+ }
+
+ private void streamWrite(final byte[] b, final int off, final int len) throws IOException {
+ Asserts.notNull(outstream, "Output stream");
+ this.outstream.write(b, off, len);
+ }
+
+ private void flushStream() throws IOException {
+ if (this.outstream != null) {
+ this.outstream.flush();
+ }
+ }
+
+ private void flushBuffer() throws IOException {
+ final int len = this.buffer.length();
+ if (len > 0) {
+ streamWrite(this.buffer.buffer(), 0, len);
+ this.buffer.clear();
+ this.metrics.incrementBytesTransferred(len);
+ }
+ }
+
+ public void flush() throws IOException {
+ flushBuffer();
+ flushStream();
+ }
+
+ public void write(final byte[] b, final int off, final int len) throws IOException {
+ if (b == null) {
+ return;
+ }
+ // Do not want to buffer large-ish chunks
+ // if the byte array is larger then MIN_CHUNK_LIMIT
+ // write it directly to the output stream
+ if (len > this.fragementSizeHint || len > this.buffer.capacity()) {
+ // flush the buffer
+ flushBuffer();
+ // write directly to the out stream
+ streamWrite(b, off, len);
+ this.metrics.incrementBytesTransferred(len);
+ } else {
+ // Do not let the buffer grow unnecessarily
+ final int freecapacity = this.buffer.capacity() - this.buffer.length();
+ if (len > freecapacity) {
+ // flush the buffer
+ flushBuffer();
+ }
+ // buffer
+ this.buffer.append(b, off, len);
+ }
+ }
+
+ public void write(final byte[] b) throws IOException {
+ if (b == null) {
+ return;
+ }
+ write(b, 0, b.length);
+ }
+
+ public void write(final int b) throws IOException {
+ if (this.fragementSizeHint > 0) {
+ if (this.buffer.isFull()) {
+ flushBuffer();
+ }
+ this.buffer.append(b);
+ } else {
+ flushBuffer();
+ this.outstream.write(b);
+ }
+ }
+
+ /**
+ * Writes characters from the specified string followed by a line delimiter
+ * to this session buffer.
+ * <p>
+ * This method uses CR-LF as a line delimiter.
+ *
+ * @param s the line.
+ * @exception IOException if an I/O error occurs.
+ */
+ public void writeLine(final String s) throws IOException {
+ if (s == null) {
+ return;
+ }
+ if (s.length() > 0) {
+ if (this.encoder == null) {
+ for (int i = 0; i < s.length(); i++) {
+ write(s.charAt(i));
+ }
+ } else {
+ final CharBuffer cbuf = CharBuffer.wrap(s);
+ writeEncoded(cbuf);
+ }
+ }
+ write(CRLF);
+ }
+
+ /**
+ * Writes characters from the specified char array followed by a line
+ * delimiter to this session buffer.
+ * <p>
+ * This method uses CR-LF as a line delimiter.
+ *
+ * @param charbuffer the buffer containing chars of the line.
+ * @exception IOException if an I/O error occurs.
+ */
+ public void writeLine(final CharArrayBuffer charbuffer) throws IOException {
+ if (charbuffer == null) {
+ return;
+ }
+ if (this.encoder == null) {
+ int off = 0;
+ int remaining = charbuffer.length();
+ while (remaining > 0) {
+ int chunk = this.buffer.capacity() - this.buffer.length();
+ chunk = Math.min(chunk, remaining);
+ if (chunk > 0) {
+ this.buffer.append(charbuffer, off, chunk);
+ }
+ if (this.buffer.isFull()) {
+ flushBuffer();
+ }
+ off += chunk;
+ remaining -= chunk;
+ }
+ } else {
+ final CharBuffer cbuf = CharBuffer.wrap(charbuffer.buffer(), 0, charbuffer.length());
+ writeEncoded(cbuf);
+ }
+ write(CRLF);
+ }
+
+ private void writeEncoded(final CharBuffer cbuf) throws IOException {
+ if (!cbuf.hasRemaining()) {
+ return;
+ }
+ if (this.bbuf == null) {
+ this.bbuf = ByteBuffer.allocate(1024);
+ }
+ this.encoder.reset();
+ while (cbuf.hasRemaining()) {
+ final CoderResult result = this.encoder.encode(cbuf, this.bbuf, true);
+ handleEncodingResult(result);
+ }
+ final CoderResult result = this.encoder.flush(this.bbuf);
+ handleEncodingResult(result);
+ this.bbuf.clear();
+ }
+
+ private void handleEncodingResult(final CoderResult result) throws IOException {
+ if (result.isError()) {
+ result.throwException();
+ }
+ this.bbuf.flip();
+ while (this.bbuf.hasRemaining()) {
+ write(this.bbuf.get());
+ }
+ this.bbuf.compact();
+ }
+
+ public HttpTransportMetrics getMetrics() {
+ return this.metrics;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketInputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketInputBuffer.java
new file mode 100644
index 000000000..4bba8f894
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketInputBuffer.java
@@ -0,0 +1,108 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.io.EofSensor;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * {@link ch.boye.httpclientandroidlib.io.SessionInputBuffer} implementation
+ * bound to a {@link Socket}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link SessionInputBufferImpl}
+ */
+@NotThreadSafe
+@Deprecated
+public class SocketInputBuffer extends AbstractSessionInputBuffer implements EofSensor {
+
+ private final Socket socket;
+
+ private boolean eof;
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param socket the socket to read data from.
+ * @param buffersize the size of the internal buffer. If this number is less
+ * than <code>0</code> it is set to the value of
+ * {@link Socket#getReceiveBufferSize()}. If resultant number is less
+ * than <code>1024</code> it is set to <code>1024</code>.
+ * @param params HTTP parameters.
+ */
+ public SocketInputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ super();
+ Args.notNull(socket, "Socket");
+ this.socket = socket;
+ this.eof = false;
+ int n = buffersize;
+ if (n < 0) {
+ n = socket.getReceiveBufferSize();
+ }
+ if (n < 1024) {
+ n = 1024;
+ }
+ init(socket.getInputStream(), n, params);
+ }
+
+ @Override
+ protected int fillBuffer() throws IOException {
+ final int i = super.fillBuffer();
+ this.eof = i == -1;
+ return i;
+ }
+
+ public boolean isDataAvailable(final int timeout) throws IOException {
+ boolean result = hasBufferedData();
+ if (!result) {
+ final int oldtimeout = this.socket.getSoTimeout();
+ try {
+ this.socket.setSoTimeout(timeout);
+ fillBuffer();
+ result = hasBufferedData();
+ } finally {
+ socket.setSoTimeout(oldtimeout);
+ }
+ }
+ return result;
+ }
+
+ public boolean isEof() {
+ return this.eof;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketOutputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketOutputBuffer.java
new file mode 100644
index 000000000..9c9ff2d9f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/SocketOutputBuffer.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.impl.io;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * {@link ch.boye.httpclientandroidlib.io.SessionOutputBuffer} implementation
+ * bound to a {@link Socket}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link SessionOutputBufferImpl}
+ */
+@NotThreadSafe
+@Deprecated
+public class SocketOutputBuffer extends AbstractSessionOutputBuffer {
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param socket the socket to write data to.
+ * @param buffersize the size of the internal buffer. If this number is less
+ * than <code>0</code> it is set to the value of
+ * {@link Socket#getSendBufferSize()}. If resultant number is less
+ * than <code>1024</code> it is set to <code>1024</code>.
+ * @param params HTTP parameters.
+ */
+ public SocketOutputBuffer(
+ final Socket socket,
+ final int buffersize,
+ final HttpParams params) throws IOException {
+ super();
+ Args.notNull(socket, "Socket");
+ int n = buffersize;
+ if (n < 0) {
+ n = socket.getSendBufferSize();
+ }
+ if (n < 1024) {
+ n = 1024;
+ }
+ init(socket.getOutputStream(), n, params);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/package-info.java
new file mode 100644
index 000000000..24c7bee79
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/io/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default implementations of message parses and writers
+ * for synchronous, blocking communication.
+ */
+package ch.boye.httpclientandroidlib.impl.io;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/package-info.java
new file mode 100644
index 000000000..4cf3cdb3a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default implementations of HTTP connections for synchronous,
+ * blocking communication.
+ */
+package ch.boye.httpclientandroidlib.impl;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnFactory.java
new file mode 100644
index 000000000..a9e26a435
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnFactory.java
@@ -0,0 +1,177 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.pool;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLSocketFactory;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpConnectionFactory;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.config.SocketConfig;
+import ch.boye.httpclientandroidlib.impl.DefaultBHttpClientConnection;
+import ch.boye.httpclientandroidlib.impl.DefaultBHttpClientConnectionFactory;
+import ch.boye.httpclientandroidlib.params.CoreConnectionPNames;
+import ch.boye.httpclientandroidlib.params.HttpParamConfig;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.pool.ConnFactory;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * A very basic {@link ConnFactory} implementation that creates
+ * {@link HttpClientConnection} instances given a {@link HttpHost} instance.
+ *
+ * @see HttpHost
+ * @since 4.2
+ */
+@SuppressWarnings("deprecation")
+@Immutable
+public class BasicConnFactory implements ConnFactory<HttpHost, HttpClientConnection> {
+
+ private final SocketFactory plainfactory;
+ private final SSLSocketFactory sslfactory;
+ private final int connectTimeout;
+ private final SocketConfig sconfig;
+ private final HttpConnectionFactory<? extends HttpClientConnection> connFactory;
+
+ /**
+ * @deprecated (4.3) use
+ * {@link BasicConnFactory#BasicConnFactory(SocketFactory, SSLSocketFactory, int,
+ * SocketConfig, ConnectionConfig)}.
+ */
+ @Deprecated
+ public BasicConnFactory(final SSLSocketFactory sslfactory, final HttpParams params) {
+ super();
+ Args.notNull(params, "HTTP params");
+ this.plainfactory = null;
+ this.sslfactory = sslfactory;
+ this.connectTimeout = params.getIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 0);
+ this.sconfig = HttpParamConfig.getSocketConfig(params);
+ this.connFactory = new DefaultBHttpClientConnectionFactory(
+ HttpParamConfig.getConnectionConfig(params));
+ }
+
+ /**
+ * @deprecated (4.3) use
+ * {@link BasicConnFactory#BasicConnFactory(int, SocketConfig, ConnectionConfig)}.
+ */
+ @Deprecated
+ public BasicConnFactory(final HttpParams params) {
+ this(null, params);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public BasicConnFactory(
+ final SocketFactory plainfactory,
+ final SSLSocketFactory sslfactory,
+ final int connectTimeout,
+ final SocketConfig sconfig,
+ final ConnectionConfig cconfig) {
+ super();
+ this.plainfactory = plainfactory;
+ this.sslfactory = sslfactory;
+ this.connectTimeout = connectTimeout;
+ this.sconfig = sconfig != null ? sconfig : SocketConfig.DEFAULT;
+ this.connFactory = new DefaultBHttpClientConnectionFactory(
+ cconfig != null ? cconfig : ConnectionConfig.DEFAULT);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public BasicConnFactory(
+ final int connectTimeout, final SocketConfig sconfig, final ConnectionConfig cconfig) {
+ this(null, null, connectTimeout, sconfig, cconfig);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public BasicConnFactory(final SocketConfig sconfig, final ConnectionConfig cconfig) {
+ this(null, null, 0, sconfig, cconfig);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public BasicConnFactory() {
+ this(null, null, 0, SocketConfig.DEFAULT, ConnectionConfig.DEFAULT);
+ }
+
+ /**
+ * @deprecated (4.3) no longer used.
+ */
+ @Deprecated
+ protected HttpClientConnection create(final Socket socket, final HttpParams params) throws IOException {
+ final int bufsize = params.getIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024);
+ final DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(bufsize);
+ conn.bind(socket);
+ return conn;
+ }
+
+ public HttpClientConnection create(final HttpHost host) throws IOException {
+ final String scheme = host.getSchemeName();
+ Socket socket = null;
+ if ("http".equalsIgnoreCase(scheme)) {
+ socket = this.plainfactory != null ? this.plainfactory.createSocket() :
+ new Socket();
+ } if ("https".equalsIgnoreCase(scheme)) {
+ socket = (this.sslfactory != null ? this.sslfactory :
+ SSLSocketFactory.getDefault()).createSocket();
+ }
+ if (socket == null) {
+ throw new IOException(scheme + " scheme is not supported");
+ }
+ final String hostname = host.getHostName();
+ int port = host.getPort();
+ if (port == -1) {
+ if (host.getSchemeName().equalsIgnoreCase("http")) {
+ port = 80;
+ } else if (host.getSchemeName().equalsIgnoreCase("https")) {
+ port = 443;
+ }
+ }
+ socket.setSoTimeout(this.sconfig.getSoTimeout());
+ socket.connect(new InetSocketAddress(hostname, port), this.connectTimeout);
+ socket.setTcpNoDelay(this.sconfig.isTcpNoDelay());
+ final int linger = this.sconfig.getSoLinger();
+ if (linger >= 0) {
+ socket.setSoLinger(linger > 0, linger);
+ }
+ socket.setKeepAlive(this.sconfig.isSoKeepAlive());
+ return this.connFactory.createConnection(socket);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnPool.java
new file mode 100644
index 000000000..c99badd3e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicConnPool.java
@@ -0,0 +1,89 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.pool;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.config.SocketConfig;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.pool.AbstractConnPool;
+import ch.boye.httpclientandroidlib.pool.ConnFactory;
+
+/**
+ * A very basic {@link ch.boye.httpclientandroidlib.pool.ConnPool} implementation that
+ * represents a pool of blocking {@link HttpClientConnection} connections
+ * identified by an {@link HttpHost} instance. Please note this pool
+ * implementation does not support complex routes via a proxy cannot
+ * differentiate between direct and proxied connections.
+ *
+ * @see HttpHost
+ * @since 4.2
+ */
+@SuppressWarnings("deprecation")
+@ThreadSafe
+public class BasicConnPool extends AbstractConnPool<HttpHost, HttpClientConnection, BasicPoolEntry> {
+
+ private static final AtomicLong COUNTER = new AtomicLong();
+
+ public BasicConnPool(final ConnFactory<HttpHost, HttpClientConnection> connFactory) {
+ super(connFactory, 2, 20);
+ }
+
+ /**
+ * @deprecated (4.3) use {@link BasicConnPool#BasicConnPool(SocketConfig, ConnectionConfig)}
+ */
+ @Deprecated
+ public BasicConnPool(final HttpParams params) {
+ super(new BasicConnFactory(params), 2, 20);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public BasicConnPool(final SocketConfig sconfig, final ConnectionConfig cconfig) {
+ super(new BasicConnFactory(sconfig, cconfig), 2, 20);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public BasicConnPool() {
+ super(new BasicConnFactory(SocketConfig.DEFAULT, ConnectionConfig.DEFAULT), 2, 20);
+ }
+
+ @Override
+ protected BasicPoolEntry createEntry(
+ final HttpHost host,
+ final HttpClientConnection conn) {
+ return new BasicPoolEntry(Long.toString(COUNTER.getAndIncrement()), host, conn);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicPoolEntry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicPoolEntry.java
new file mode 100644
index 000000000..465525c33
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/BasicPoolEntry.java
@@ -0,0 +1,64 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.impl.pool;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.pool.PoolEntry;
+
+/**
+ * A very basic {@link PoolEntry} implementation that represents an entry
+ * in a pool of blocking {@link HttpClientConnection}s identified by
+ * an {@link HttpHost} instance.
+ *
+ * @see HttpHost
+ * @since 4.2
+ */
+@ThreadSafe
+public class BasicPoolEntry extends PoolEntry<HttpHost, HttpClientConnection> {
+
+ public BasicPoolEntry(final String id, final HttpHost route, final HttpClientConnection conn) {
+ super(id, route, conn);
+ }
+
+ @Override
+ public void close() {
+ try {
+ this.getConnection().close();
+ } catch (final IOException ignore) {
+ }
+ }
+
+ @Override
+ public boolean isClosed() {
+ return !this.getConnection().isOpen();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/package-info.java
new file mode 100644
index 000000000..534e1885c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/pool/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Default implementations of client side connection pools
+ * for synchronous, blocking communication.
+ */
+package ch.boye.httpclientandroidlib.impl.pool;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/BufferInfo.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/BufferInfo.java
new file mode 100644
index 000000000..b75ddd8fc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/BufferInfo.java
@@ -0,0 +1,58 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+/**
+ * Basic buffer properties.
+ *
+ * @since 4.1
+ */
+public interface BufferInfo {
+
+ /**
+ * Return length data stored in the buffer
+ *
+ * @return data length
+ */
+ int length();
+
+ /**
+ * Returns total capacity of the buffer
+ *
+ * @return total capacity
+ */
+ int capacity();
+
+ /**
+ * Returns available space in the buffer.
+ *
+ * @return available space.
+ */
+ int available();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/EofSensor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/EofSensor.java
new file mode 100644
index 000000000..bd577b7e4
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/EofSensor.java
@@ -0,0 +1,42 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+/**
+ * EOF sensor.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) no longer used.
+ */
+@Deprecated
+public interface EofSensor {
+
+ boolean isEof();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParser.java
new file mode 100644
index 000000000..2a6f4f3f8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParser.java
@@ -0,0 +1,56 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+
+/**
+ * Abstract message parser intended to build HTTP messages from an arbitrary data source.
+ *
+ * @param <T>
+ * {@link HttpMessage} or a subclass
+ *
+ * @since 4.0
+ */
+public interface HttpMessageParser<T extends HttpMessage> {
+
+ /**
+ * Generates an instance of {@link HttpMessage} from the underlying data
+ * source.
+ *
+ * @return HTTP message
+ * @throws IOException in case of an I/O error
+ * @throws HttpException in case of HTTP protocol violation
+ */
+ T parse()
+ throws IOException, HttpException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParserFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParserFactory.java
new file mode 100644
index 000000000..c550120a5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageParserFactory.java
@@ -0,0 +1,42 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+
+/**
+ * Factory for {@link HttpMessageParser} instances.
+ *
+ * @since 4.3
+ */
+public interface HttpMessageParserFactory<T extends HttpMessage> {
+
+ HttpMessageParser<T> create(SessionInputBuffer buffer, MessageConstraints constraints);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriter.java
new file mode 100644
index 000000000..7b4557e92
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriter.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpMessage;
+
+/**
+ * Abstract message writer intended to serialize HTTP messages to an arbitrary
+ * data sink.
+ *
+ * @since 4.0
+ */
+public interface HttpMessageWriter<T extends HttpMessage> {
+
+ /**
+ * Serializes an instance of {@link HttpMessage} to the underlying data
+ * sink.
+ *
+ * @param message HTTP message
+ * @throws IOException in case of an I/O error
+ * @throws HttpException in case of HTTP protocol violation
+ */
+ void write(T message)
+ throws IOException, HttpException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriterFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriterFactory.java
new file mode 100644
index 000000000..3e8ad0552
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpMessageWriterFactory.java
@@ -0,0 +1,41 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+import ch.boye.httpclientandroidlib.HttpMessage;
+
+/**
+ * Factory for {@link HttpMessageWriter} instances.
+ *
+ * @since 4.3
+ */
+public interface HttpMessageWriterFactory<T extends HttpMessage> {
+
+ HttpMessageWriter<T> create(SessionOutputBuffer buffer);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpTransportMetrics.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpTransportMetrics.java
new file mode 100644
index 000000000..6eeb6ede1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/HttpTransportMetrics.java
@@ -0,0 +1,48 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+/**
+ * The point of access to the statistics of {@link SessionInputBuffer} or
+ * {@link SessionOutputBuffer}.
+ *
+ * @since 4.0
+ */
+public interface HttpTransportMetrics {
+
+ /**
+ * Returns the number of bytes transferred.
+ */
+ long getBytesTransferred();
+
+ /**
+ * Resets the counts
+ */
+ void reset();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionInputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionInputBuffer.java
new file mode 100644
index 000000000..80417801d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionInputBuffer.java
@@ -0,0 +1,152 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Session input buffer for blocking connections. This interface is similar to
+ * InputStream class, but it also provides methods for reading lines of text.
+ * <p>
+ * Implementing classes are also expected to manage intermediate data buffering
+ * for optimal input performance.
+ *
+ * @since 4.0
+ */
+public interface SessionInputBuffer {
+
+ /**
+ * Reads up to <code>len</code> bytes of data from the session buffer into
+ * an array of bytes. An attempt is made to read as many as
+ * <code>len</code> bytes, but a smaller number may be read, possibly
+ * zero. The number of bytes actually read is returned as an integer.
+ *
+ * <p> This method blocks until input data is available, end of file is
+ * detected, or an exception is thrown.
+ *
+ * <p> If <code>off</code> is negative, or <code>len</code> is negative, or
+ * <code>off+len</code> is greater than the length of the array
+ * <code>b</code>, then an <code>IndexOutOfBoundsException</code> is
+ * thrown.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in array <code>b</code>
+ * at which the data is written.
+ * @param len the maximum number of bytes to read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> if there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ */
+ int read(byte[] b, int off, int len) throws IOException;
+
+ /**
+ * Reads some number of bytes from the session buffer and stores them into
+ * the buffer array <code>b</code>. The number of bytes actually read is
+ * returned as an integer. This method blocks until input data is
+ * available, end of file is detected, or an exception is thrown.
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> is there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ */
+ int read(byte[] b) throws IOException;
+
+ /**
+ * Reads the next byte of data from this session buffer. The value byte is
+ * returned as an <code>int</code> in the range <code>0</code> to
+ * <code>255</code>. If no byte is available because the end of the stream
+ * has been reached, the value <code>-1</code> is returned. This method
+ * blocks until input data is available, the end of the stream is detected,
+ * or an exception is thrown.
+ *
+ * @return the next byte of data, or <code>-1</code> if the end of the
+ * stream is reached.
+ * @exception IOException if an I/O error occurs.
+ */
+ int read() throws IOException;
+
+ /**
+ * Reads a complete line of characters up to a line delimiter from this
+ * session buffer into the given line buffer. The number of chars actually
+ * read is returned as an integer. The line delimiter itself is discarded.
+ * If no char is available because the end of the stream has been reached,
+ * the value <code>-1</code> is returned. This method blocks until input
+ * data is available, end of file is detected, or an exception is thrown.
+ * <p>
+ * The choice of a char encoding and line delimiter sequence is up to the
+ * specific implementations of this interface.
+ *
+ * @param buffer the line buffer.
+ * @return one line of characters
+ * @exception IOException if an I/O error occurs.
+ */
+ int readLine(CharArrayBuffer buffer) throws IOException;
+
+ /**
+ * Reads a complete line of characters up to a line delimiter from this
+ * session buffer. The line delimiter itself is discarded. If no char is
+ * available because the end of the stream has been reached,
+ * <code>null</code> is returned. This method blocks until input data is
+ * available, end of file is detected, or an exception is thrown.
+ * <p>
+ * The choice of a char encoding and line delimiter sequence is up to the
+ * specific implementations of this interface.
+ *
+ * @return HTTP line as a string
+ * @exception IOException if an I/O error occurs.
+ */
+ String readLine() throws IOException;
+
+ /** Blocks until some data becomes available in the session buffer or the
+ * given timeout period in milliseconds elapses. If the timeout value is
+ * <code>0</code> this method blocks indefinitely.
+ *
+ * @param timeout in milliseconds.
+ * @return <code>true</code> if some data is available in the session
+ * buffer or <code>false</code> otherwise.
+ * @exception IOException if an I/O error occurs.
+ *
+ * @deprecated (4.3) do not use. This function should be provided at the
+ * connection level
+ */
+ @Deprecated
+ boolean isDataAvailable(int timeout) throws IOException;
+
+ /**
+ * Returns {@link HttpTransportMetrics} for this session buffer.
+ *
+ * @return transport metrics.
+ */
+ HttpTransportMetrics getMetrics();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionOutputBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionOutputBuffer.java
new file mode 100644
index 000000000..544d17d5a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/SessionOutputBuffer.java
@@ -0,0 +1,120 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.io;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Session output buffer for blocking connections. This interface is similar to
+ * OutputStream class, but it also provides methods for writing lines of text.
+ * <p>
+ * Implementing classes are also expected to manage intermediate data buffering
+ * for optimal output performance.
+ *
+ * @since 4.0
+ */
+public interface SessionOutputBuffer {
+
+ /**
+ * Writes <code>len</code> bytes from the specified byte array
+ * starting at offset <code>off</code> to this session buffer.
+ * <p>
+ * If <code>off</code> is negative, or <code>len</code> is negative, or
+ * <code>off+len</code> is greater than the length of the array
+ * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if an I/O error occurs.
+ */
+ void write(byte[] b, int off, int len) throws IOException;
+
+ /**
+ * Writes <code>b.length</code> bytes from the specified byte array
+ * to this session buffer.
+ *
+ * @param b the data.
+ * @exception IOException if an I/O error occurs.
+ */
+ void write(byte[] b) throws IOException;
+
+ /**
+ * Writes the specified byte to this session buffer.
+ *
+ * @param b the <code>byte</code>.
+ * @exception IOException if an I/O error occurs.
+ */
+ void write(int b) throws IOException;
+
+ /**
+ * Writes characters from the specified string followed by a line delimiter
+ * to this session buffer.
+ * <p>
+ * The choice of a char encoding and line delimiter sequence is up to the
+ * specific implementations of this interface.
+ *
+ * @param s the line.
+ * @exception IOException if an I/O error occurs.
+ */
+ void writeLine(String s) throws IOException;
+
+ /**
+ * Writes characters from the specified char array followed by a line
+ * delimiter to this session buffer.
+ * <p>
+ * The choice of a char encoding and line delimiter sequence is up to the
+ * specific implementations of this interface.
+ *
+ * @param buffer the buffer containing chars of the line.
+ * @exception IOException if an I/O error occurs.
+ */
+ void writeLine(CharArrayBuffer buffer) throws IOException;
+
+ /**
+ * Flushes this session buffer and forces any buffered output bytes
+ * to be written out. The general contract of <code>flush</code> is
+ * that calling it is an indication that, if any bytes previously
+ * written have been buffered by the implementation of the output
+ * stream, such bytes should immediately be written to their
+ * intended destination.
+ *
+ * @exception IOException if an I/O error occurs.
+ */
+ void flush() throws IOException;
+
+ /**
+ * Returns {@link HttpTransportMetrics} for this session buffer.
+ *
+ * @return transport metrics.
+ */
+ HttpTransportMetrics getMetrics();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/package-info.java
new file mode 100644
index 000000000..8899c5ad6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/io/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * HTTP message parser and writer APIs for synchronous, blocking
+ * communication.
+ */
+package ch.boye.httpclientandroidlib.io;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/AbstractHttpMessage.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/AbstractHttpMessage.java
new file mode 100644
index 000000000..24f7aef4e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/AbstractHttpMessage.java
@@ -0,0 +1,164 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.HttpMessage;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.params.BasicHttpParams;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of {@link HttpMessage}.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@NotThreadSafe
+public abstract class AbstractHttpMessage implements HttpMessage {
+
+ protected HeaderGroup headergroup;
+
+ @Deprecated
+ protected HttpParams params;
+
+ /**
+ * @deprecated (4.3) use {@link AbstractHttpMessage#AbstractHttpMessage()}
+ */
+ @Deprecated
+ protected AbstractHttpMessage(final HttpParams params) {
+ super();
+ this.headergroup = new HeaderGroup();
+ this.params = params;
+ }
+
+ protected AbstractHttpMessage() {
+ this(null);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public boolean containsHeader(final String name) {
+ return this.headergroup.containsHeader(name);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public Header[] getHeaders(final String name) {
+ return this.headergroup.getHeaders(name);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public Header getFirstHeader(final String name) {
+ return this.headergroup.getFirstHeader(name);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public Header getLastHeader(final String name) {
+ return this.headergroup.getLastHeader(name);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public Header[] getAllHeaders() {
+ return this.headergroup.getAllHeaders();
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public void addHeader(final Header header) {
+ this.headergroup.addHeader(header);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public void addHeader(final String name, final String value) {
+ Args.notNull(name, "Header name");
+ this.headergroup.addHeader(new BasicHeader(name, value));
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public void setHeader(final Header header) {
+ this.headergroup.updateHeader(header);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public void setHeader(final String name, final String value) {
+ Args.notNull(name, "Header name");
+ this.headergroup.updateHeader(new BasicHeader(name, value));
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public void setHeaders(final Header[] headers) {
+ this.headergroup.setHeaders(headers);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public void removeHeader(final Header header) {
+ this.headergroup.removeHeader(header);
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public void removeHeaders(final String name) {
+ if (name == null) {
+ return;
+ }
+ for (final HeaderIterator i = this.headergroup.iterator(); i.hasNext(); ) {
+ final Header header = i.nextHeader();
+ if (name.equalsIgnoreCase(header.getName())) {
+ i.remove();
+ }
+ }
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public HeaderIterator headerIterator() {
+ return this.headergroup.iterator();
+ }
+
+ // non-javadoc, see interface HttpMessage
+ public HeaderIterator headerIterator(final String name) {
+ return this.headergroup.iterator(name);
+ }
+
+ /**
+ * @deprecated (4.3) use constructor parameters of configuration API provided by HttpClient
+ */
+ @Deprecated
+ public HttpParams getParams() {
+ if (this.params == null) {
+ this.params = new BasicHttpParams();
+ }
+ return this.params;
+ }
+
+ /**
+ * @deprecated (4.3) use constructor parameters of configuration API provided by HttpClient
+ */
+ @Deprecated
+ public void setParams(final HttpParams params) {
+ this.params = Args.notNull(params, "HTTP parameters");
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeader.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeader.java
new file mode 100644
index 000000000..170bf6bfe
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeader.java
@@ -0,0 +1,91 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of {@link Header}.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicHeader implements Header, Cloneable, Serializable {
+
+ private static final long serialVersionUID = -5427236326487562174L;
+
+ private final String name;
+ private final String value;
+
+ /**
+ * Constructor with name and value
+ *
+ * @param name the header name
+ * @param value the header value
+ */
+ public BasicHeader(final String name, final String value) {
+ super();
+ this.name = Args.notNull(name, "Name");
+ this.value = value;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ // no need for non-default formatting in toString()
+ return BasicLineFormatter.INSTANCE.formatHeader(null, this).toString();
+ }
+
+ public HeaderElement[] getElements() throws ParseException {
+ if (this.value != null) {
+ // result intentionally not cached, it's probably not used again
+ return BasicHeaderValueParser.parseElements(this.value, null);
+ } else {
+ return new HeaderElement[] {};
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElement.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElement.java
new file mode 100644
index 000000000..e815f2cb1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElement.java
@@ -0,0 +1,162 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Basic implementation of {@link HeaderElement}
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicHeaderElement implements HeaderElement, Cloneable {
+
+ private final String name;
+ private final String value;
+ private final NameValuePair[] parameters;
+
+ /**
+ * Constructor with name, value and parameters.
+ *
+ * @param name header element name
+ * @param value header element value. May be <tt>null</tt>
+ * @param parameters header element parameters. May be <tt>null</tt>.
+ * Parameters are copied by reference, not by value
+ */
+ public BasicHeaderElement(
+ final String name,
+ final String value,
+ final NameValuePair[] parameters) {
+ super();
+ this.name = Args.notNull(name, "Name");
+ this.value = value;
+ if (parameters != null) {
+ this.parameters = parameters;
+ } else {
+ this.parameters = new NameValuePair[] {};
+ }
+ }
+
+ /**
+ * Constructor with name and value.
+ *
+ * @param name header element name
+ * @param value header element value. May be <tt>null</tt>
+ */
+ public BasicHeaderElement(final String name, final String value) {
+ this(name, value, null);
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ public NameValuePair[] getParameters() {
+ return this.parameters.clone();
+ }
+
+ public int getParameterCount() {
+ return this.parameters.length;
+ }
+
+ public NameValuePair getParameter(final int index) {
+ // ArrayIndexOutOfBoundsException is appropriate
+ return this.parameters[index];
+ }
+
+ public NameValuePair getParameterByName(final String name) {
+ Args.notNull(name, "Name");
+ NameValuePair found = null;
+ for (final NameValuePair current : this.parameters) {
+ if (current.getName().equalsIgnoreCase(name)) {
+ found = current;
+ break;
+ }
+ }
+ return found;
+ }
+
+ @Override
+ public boolean equals(final Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object instanceof HeaderElement) {
+ final BasicHeaderElement that = (BasicHeaderElement) object;
+ return this.name.equals(that.name)
+ && LangUtils.equals(this.value, that.value)
+ && LangUtils.equals(this.parameters, that.parameters);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.name);
+ hash = LangUtils.hashCode(hash, this.value);
+ for (final NameValuePair parameter : this.parameters) {
+ hash = LangUtils.hashCode(hash, parameter);
+ }
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(this.name);
+ if (this.value != null) {
+ buffer.append("=");
+ buffer.append(this.value);
+ }
+ for (final NameValuePair parameter : this.parameters) {
+ buffer.append("; ");
+ buffer.append(parameter);
+ }
+ return buffer.toString();
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ // parameters array is considered immutable
+ // no need to make a copy of it
+ return super.clone();
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElementIterator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElementIterator.java
new file mode 100644
index 000000000..f14f00f0d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderElementIterator.java
@@ -0,0 +1,151 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.util.NoSuchElementException;
+
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HeaderElementIterator;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Basic implementation of a {@link HeaderElementIterator}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicHeaderElementIterator implements HeaderElementIterator {
+
+ private final HeaderIterator headerIt;
+ private final HeaderValueParser parser;
+
+ private HeaderElement currentElement = null;
+ private CharArrayBuffer buffer = null;
+ private ParserCursor cursor = null;
+
+ /**
+ * Creates a new instance of BasicHeaderElementIterator
+ */
+ public BasicHeaderElementIterator(
+ final HeaderIterator headerIterator,
+ final HeaderValueParser parser) {
+ this.headerIt = Args.notNull(headerIterator, "Header iterator");
+ this.parser = Args.notNull(parser, "Parser");
+ }
+
+
+ public BasicHeaderElementIterator(final HeaderIterator headerIterator) {
+ this(headerIterator, BasicHeaderValueParser.INSTANCE);
+ }
+
+
+ private void bufferHeaderValue() {
+ this.cursor = null;
+ this.buffer = null;
+ while (this.headerIt.hasNext()) {
+ final Header h = this.headerIt.nextHeader();
+ if (h instanceof FormattedHeader) {
+ this.buffer = ((FormattedHeader) h).getBuffer();
+ this.cursor = new ParserCursor(0, this.buffer.length());
+ this.cursor.updatePos(((FormattedHeader) h).getValuePos());
+ break;
+ } else {
+ final String value = h.getValue();
+ if (value != null) {
+ this.buffer = new CharArrayBuffer(value.length());
+ this.buffer.append(value);
+ this.cursor = new ParserCursor(0, this.buffer.length());
+ break;
+ }
+ }
+ }
+ }
+
+ private void parseNextElement() {
+ // loop while there are headers left to parse
+ while (this.headerIt.hasNext() || this.cursor != null) {
+ if (this.cursor == null || this.cursor.atEnd()) {
+ // get next header value
+ bufferHeaderValue();
+ }
+ // Anything buffered?
+ if (this.cursor != null) {
+ // loop while there is data in the buffer
+ while (!this.cursor.atEnd()) {
+ final HeaderElement e = this.parser.parseHeaderElement(this.buffer, this.cursor);
+ if (!(e.getName().length() == 0 && e.getValue() == null)) {
+ // Found something
+ this.currentElement = e;
+ return;
+ }
+ }
+ // if at the end of the buffer
+ if (this.cursor.atEnd()) {
+ // discard it
+ this.cursor = null;
+ this.buffer = null;
+ }
+ }
+ }
+ }
+
+ public boolean hasNext() {
+ if (this.currentElement == null) {
+ parseNextElement();
+ }
+ return this.currentElement != null;
+ }
+
+ public HeaderElement nextElement() throws NoSuchElementException {
+ if (this.currentElement == null) {
+ parseNextElement();
+ }
+
+ if (this.currentElement == null) {
+ throw new NoSuchElementException("No more header elements available");
+ }
+
+ final HeaderElement element = this.currentElement;
+ this.currentElement = null;
+ return element;
+ }
+
+ public final Object next() throws NoSuchElementException {
+ return nextElement();
+ }
+
+ public void remove() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Remove not supported");
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderIterator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderIterator.java
new file mode 100644
index 000000000..5c8c87fbf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderIterator.java
@@ -0,0 +1,175 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.util.NoSuchElementException;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of a {@link HeaderIterator}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicHeaderIterator implements HeaderIterator {
+
+ /**
+ * An array of headers to iterate over.
+ * Not all elements of this array are necessarily part of the iteration.
+ * This array will never be modified by the iterator.
+ * Derived implementations are expected to adhere to this restriction.
+ */
+ protected final Header[] allHeaders;
+
+
+ /**
+ * The position of the next header in {@link #allHeaders allHeaders}.
+ * Negative if the iteration is over.
+ */
+ protected int currentIndex;
+
+
+ /**
+ * The header name to filter by.
+ * <code>null</code> to iterate over all headers in the array.
+ */
+ protected String headerName;
+
+
+
+ /**
+ * Creates a new header iterator.
+ *
+ * @param headers an array of headers over which to iterate
+ * @param name the name of the headers over which to iterate, or
+ * <code>null</code> for any
+ */
+ public BasicHeaderIterator(final Header[] headers, final String name) {
+ super();
+ this.allHeaders = Args.notNull(headers, "Header array");
+ this.headerName = name;
+ this.currentIndex = findNext(-1);
+ }
+
+
+ /**
+ * Determines the index of the next header.
+ *
+ * @param pos one less than the index to consider first,
+ * -1 to search for the first header
+ *
+ * @return the index of the next header that matches the filter name,
+ * or negative if there are no more headers
+ */
+ protected int findNext(final int pos) {
+ int from = pos;
+ if (from < -1) {
+ return -1;
+ }
+
+ final int to = this.allHeaders.length-1;
+ boolean found = false;
+ while (!found && (from < to)) {
+ from++;
+ found = filterHeader(from);
+ }
+ return found ? from : -1;
+ }
+
+
+ /**
+ * Checks whether a header is part of the iteration.
+ *
+ * @param index the index of the header to check
+ *
+ * @return <code>true</code> if the header should be part of the
+ * iteration, <code>false</code> to skip
+ */
+ protected boolean filterHeader(final int index) {
+ return (this.headerName == null) ||
+ this.headerName.equalsIgnoreCase(this.allHeaders[index].getName());
+ }
+
+
+ // non-javadoc, see interface HeaderIterator
+ public boolean hasNext() {
+ return (this.currentIndex >= 0);
+ }
+
+
+ /**
+ * Obtains the next header from this iteration.
+ *
+ * @return the next header in this iteration
+ *
+ * @throws NoSuchElementException if there are no more headers
+ */
+ public Header nextHeader()
+ throws NoSuchElementException {
+
+ final int current = this.currentIndex;
+ if (current < 0) {
+ throw new NoSuchElementException("Iteration already finished.");
+ }
+
+ this.currentIndex = findNext(current);
+
+ return this.allHeaders[current];
+ }
+
+
+ /**
+ * Returns the next header.
+ * Same as {@link #nextHeader nextHeader}, but not type-safe.
+ *
+ * @return the next header in this iteration
+ *
+ * @throws NoSuchElementException if there are no more headers
+ */
+ public final Object next()
+ throws NoSuchElementException {
+ return nextHeader();
+ }
+
+
+ /**
+ * Removing headers is not supported.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public void remove()
+ throws UnsupportedOperationException {
+
+ throw new UnsupportedOperationException
+ ("Removing headers is not supported.");
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueFormatter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueFormatter.java
new file mode 100644
index 000000000..b7e731759
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueFormatter.java
@@ -0,0 +1,422 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Basic implementation for formatting header value elements.
+ * Instances of this class are stateless and thread-safe.
+ * Derived classes are expected to maintain these properties.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicHeaderValueFormatter implements HeaderValueFormatter {
+
+ /**
+ * A default instance of this class, for use as default or fallback.
+ * Note that {@link BasicHeaderValueFormatter} is not a singleton, there
+ * can be many instances of the class itself and of derived classes.
+ * The instance here provides non-customized, default behavior.
+ *
+ * @deprecated (4.3) use {@link #INSTANCE}
+ */
+ @Deprecated
+ public final static
+ BasicHeaderValueFormatter DEFAULT = new BasicHeaderValueFormatter();
+
+ public final static BasicHeaderValueFormatter INSTANCE = new BasicHeaderValueFormatter();
+
+ /**
+ * Special characters that can be used as separators in HTTP parameters.
+ * These special characters MUST be in a quoted string to be used within
+ * a parameter value .
+ */
+ public final static String SEPARATORS = " ;,:@()<>\\\"/[]?={}\t";
+
+ /**
+ * Unsafe special characters that must be escaped using the backslash
+ * character
+ */
+ public final static String UNSAFE_CHARS = "\"\\";
+
+ public BasicHeaderValueFormatter() {
+ super();
+ }
+
+ /**
+ * Formats an array of header elements.
+ *
+ * @param elems the header elements to format
+ * @param quote <code>true</code> to always format with quoted values,
+ * <code>false</code> to use quotes only when necessary
+ * @param formatter the formatter to use, or <code>null</code>
+ * for the {@link #INSTANCE default}
+ *
+ * @return the formatted header elements
+ */
+ public static
+ String formatElements(final HeaderElement[] elems,
+ final boolean quote,
+ final HeaderValueFormatter formatter) {
+ return (formatter != null ? formatter : BasicHeaderValueFormatter.INSTANCE)
+ .formatElements(null, elems, quote).toString();
+ }
+
+
+ // non-javadoc, see interface HeaderValueFormatter
+ public CharArrayBuffer formatElements(final CharArrayBuffer charBuffer,
+ final HeaderElement[] elems,
+ final boolean quote) {
+ Args.notNull(elems, "Header element array");
+ final int len = estimateElementsLen(elems);
+ CharArrayBuffer buffer = charBuffer;
+ if (buffer == null) {
+ buffer = new CharArrayBuffer(len);
+ } else {
+ buffer.ensureCapacity(len);
+ }
+
+ for (int i=0; i<elems.length; i++) {
+ if (i > 0) {
+ buffer.append(", ");
+ }
+ formatHeaderElement(buffer, elems[i], quote);
+ }
+
+ return buffer;
+ }
+
+
+ /**
+ * Estimates the length of formatted header elements.
+ *
+ * @param elems the header elements to format, or <code>null</code>
+ *
+ * @return a length estimate, in number of characters
+ */
+ protected int estimateElementsLen(final HeaderElement[] elems) {
+ if ((elems == null) || (elems.length < 1)) {
+ return 0;
+ }
+
+ int result = (elems.length-1) * 2; // elements separated by ", "
+ for (final HeaderElement elem : elems) {
+ result += estimateHeaderElementLen(elem);
+ }
+
+ return result;
+ }
+
+
+
+ /**
+ * Formats a header element.
+ *
+ * @param elem the header element to format
+ * @param quote <code>true</code> to always format with quoted values,
+ * <code>false</code> to use quotes only when necessary
+ * @param formatter the formatter to use, or <code>null</code>
+ * for the {@link #INSTANCE default}
+ *
+ * @return the formatted header element
+ */
+ public static
+ String formatHeaderElement(final HeaderElement elem,
+ final boolean quote,
+ final HeaderValueFormatter formatter) {
+ return (formatter != null ? formatter : BasicHeaderValueFormatter.INSTANCE)
+ .formatHeaderElement(null, elem, quote).toString();
+ }
+
+
+ // non-javadoc, see interface HeaderValueFormatter
+ public CharArrayBuffer formatHeaderElement(final CharArrayBuffer charBuffer,
+ final HeaderElement elem,
+ final boolean quote) {
+ Args.notNull(elem, "Header element");
+ final int len = estimateHeaderElementLen(elem);
+ CharArrayBuffer buffer = charBuffer;
+ if (buffer == null) {
+ buffer = new CharArrayBuffer(len);
+ } else {
+ buffer.ensureCapacity(len);
+ }
+
+ buffer.append(elem.getName());
+ final String value = elem.getValue();
+ if (value != null) {
+ buffer.append('=');
+ doFormatValue(buffer, value, quote);
+ }
+
+ final int parcnt = elem.getParameterCount();
+ if (parcnt > 0) {
+ for (int i=0; i<parcnt; i++) {
+ buffer.append("; ");
+ formatNameValuePair(buffer, elem.getParameter(i), quote);
+ }
+ }
+
+ return buffer;
+ }
+
+
+ /**
+ * Estimates the length of a formatted header element.
+ *
+ * @param elem the header element to format, or <code>null</code>
+ *
+ * @return a length estimate, in number of characters
+ */
+ protected int estimateHeaderElementLen(final HeaderElement elem) {
+ if (elem == null) {
+ return 0;
+ }
+
+ int result = elem.getName().length(); // name
+ final String value = elem.getValue();
+ if (value != null) {
+ // assume quotes, but no escaped characters
+ result += 3 + value.length(); // ="value"
+ }
+
+ final int parcnt = elem.getParameterCount();
+ if (parcnt > 0) {
+ for (int i=0; i<parcnt; i++) {
+ result += 2 + // ; <param>
+ estimateNameValuePairLen(elem.getParameter(i));
+ }
+ }
+
+ return result;
+ }
+
+
+
+
+ /**
+ * Formats a set of parameters.
+ *
+ * @param nvps the parameters to format
+ * @param quote <code>true</code> to always format with quoted values,
+ * <code>false</code> to use quotes only when necessary
+ * @param formatter the formatter to use, or <code>null</code>
+ * for the {@link #INSTANCE default}
+ *
+ * @return the formatted parameters
+ */
+ public static
+ String formatParameters(final NameValuePair[] nvps,
+ final boolean quote,
+ final HeaderValueFormatter formatter) {
+ return (formatter != null ? formatter : BasicHeaderValueFormatter.INSTANCE)
+ .formatParameters(null, nvps, quote).toString();
+ }
+
+
+ // non-javadoc, see interface HeaderValueFormatter
+ public CharArrayBuffer formatParameters(final CharArrayBuffer charBuffer,
+ final NameValuePair[] nvps,
+ final boolean quote) {
+ Args.notNull(nvps, "Header parameter array");
+ final int len = estimateParametersLen(nvps);
+ CharArrayBuffer buffer = charBuffer;
+ if (buffer == null) {
+ buffer = new CharArrayBuffer(len);
+ } else {
+ buffer.ensureCapacity(len);
+ }
+
+ for (int i = 0; i < nvps.length; i++) {
+ if (i > 0) {
+ buffer.append("; ");
+ }
+ formatNameValuePair(buffer, nvps[i], quote);
+ }
+
+ return buffer;
+ }
+
+
+ /**
+ * Estimates the length of formatted parameters.
+ *
+ * @param nvps the parameters to format, or <code>null</code>
+ *
+ * @return a length estimate, in number of characters
+ */
+ protected int estimateParametersLen(final NameValuePair[] nvps) {
+ if ((nvps == null) || (nvps.length < 1)) {
+ return 0;
+ }
+
+ int result = (nvps.length-1) * 2; // "; " between the parameters
+ for (final NameValuePair nvp : nvps) {
+ result += estimateNameValuePairLen(nvp);
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Formats a name-value pair.
+ *
+ * @param nvp the name-value pair to format
+ * @param quote <code>true</code> to always format with a quoted value,
+ * <code>false</code> to use quotes only when necessary
+ * @param formatter the formatter to use, or <code>null</code>
+ * for the {@link #INSTANCE default}
+ *
+ * @return the formatted name-value pair
+ */
+ public static
+ String formatNameValuePair(final NameValuePair nvp,
+ final boolean quote,
+ final HeaderValueFormatter formatter) {
+ return (formatter != null ? formatter : BasicHeaderValueFormatter.INSTANCE)
+ .formatNameValuePair(null, nvp, quote).toString();
+ }
+
+
+ // non-javadoc, see interface HeaderValueFormatter
+ public CharArrayBuffer formatNameValuePair(final CharArrayBuffer charBuffer,
+ final NameValuePair nvp,
+ final boolean quote) {
+ Args.notNull(nvp, "Name / value pair");
+ final int len = estimateNameValuePairLen(nvp);
+ CharArrayBuffer buffer = charBuffer;
+ if (buffer == null) {
+ buffer = new CharArrayBuffer(len);
+ } else {
+ buffer.ensureCapacity(len);
+ }
+
+ buffer.append(nvp.getName());
+ final String value = nvp.getValue();
+ if (value != null) {
+ buffer.append('=');
+ doFormatValue(buffer, value, quote);
+ }
+
+ return buffer;
+ }
+
+
+ /**
+ * Estimates the length of a formatted name-value pair.
+ *
+ * @param nvp the name-value pair to format, or <code>null</code>
+ *
+ * @return a length estimate, in number of characters
+ */
+ protected int estimateNameValuePairLen(final NameValuePair nvp) {
+ if (nvp == null) {
+ return 0;
+ }
+
+ int result = nvp.getName().length(); // name
+ final String value = nvp.getValue();
+ if (value != null) {
+ // assume quotes, but no escaped characters
+ result += 3 + value.length(); // ="value"
+ }
+ return result;
+ }
+
+
+ /**
+ * Actually formats the value of a name-value pair.
+ * This does not include a leading = character.
+ * Called from {@link #formatNameValuePair formatNameValuePair}.
+ *
+ * @param buffer the buffer to append to, never <code>null</code>
+ * @param value the value to append, never <code>null</code>
+ * @param quote <code>true</code> to always format with quotes,
+ * <code>false</code> to use quotes only when necessary
+ */
+ protected void doFormatValue(final CharArrayBuffer buffer,
+ final String value,
+ final boolean quote) {
+
+ boolean quoteFlag = quote;
+ if (!quoteFlag) {
+ for (int i = 0; (i < value.length()) && !quoteFlag; i++) {
+ quoteFlag = isSeparator(value.charAt(i));
+ }
+ }
+
+ if (quoteFlag) {
+ buffer.append('"');
+ }
+ for (int i = 0; i < value.length(); i++) {
+ final char ch = value.charAt(i);
+ if (isUnsafe(ch)) {
+ buffer.append('\\');
+ }
+ buffer.append(ch);
+ }
+ if (quoteFlag) {
+ buffer.append('"');
+ }
+ }
+
+
+ /**
+ * Checks whether a character is a {@link #SEPARATORS separator}.
+ *
+ * @param ch the character to check
+ *
+ * @return <code>true</code> if the character is a separator,
+ * <code>false</code> otherwise
+ */
+ protected boolean isSeparator(final char ch) {
+ return SEPARATORS.indexOf(ch) >= 0;
+ }
+
+
+ /**
+ * Checks whether a character is {@link #UNSAFE_CHARS unsafe}.
+ *
+ * @param ch the character to check
+ *
+ * @return <code>true</code> if the character is unsafe,
+ * <code>false</code> otherwise
+ */
+ protected boolean isUnsafe(final char ch) {
+ return UNSAFE_CHARS.indexOf(ch) >= 0;
+ }
+
+
+} // class BasicHeaderValueFormatter
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueParser.java
new file mode 100644
index 000000000..2e23b23bf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHeaderValueParser.java
@@ -0,0 +1,359 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Basic implementation for parsing header values into elements.
+ * Instances of this class are stateless and thread-safe.
+ * Derived classes are expected to maintain these properties.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicHeaderValueParser implements HeaderValueParser {
+
+ /**
+ * A default instance of this class, for use as default or fallback.
+ * Note that {@link BasicHeaderValueParser} is not a singleton, there
+ * can be many instances of the class itself and of derived classes.
+ * The instance here provides non-customized, default behavior.
+ *
+ * @deprecated (4.3) use {@link #INSTANCE}
+ */
+ @Deprecated
+ public final static
+ BasicHeaderValueParser DEFAULT = new BasicHeaderValueParser();
+
+ public final static BasicHeaderValueParser INSTANCE = new BasicHeaderValueParser();
+
+ private final static char PARAM_DELIMITER = ';';
+ private final static char ELEM_DELIMITER = ',';
+ private final static char[] ALL_DELIMITERS = new char[] {
+ PARAM_DELIMITER,
+ ELEM_DELIMITER
+ };
+
+ public BasicHeaderValueParser() {
+ super();
+ }
+
+ /**
+ * Parses elements with the given parser.
+ *
+ * @param value the header value to parse
+ * @param parser the parser to use, or <code>null</code> for default
+ *
+ * @return array holding the header elements, never <code>null</code>
+ */
+ public static
+ HeaderElement[] parseElements(final String value,
+ final HeaderValueParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ final ParserCursor cursor = new ParserCursor(0, value.length());
+ return (parser != null ? parser : BasicHeaderValueParser.INSTANCE)
+ .parseElements(buffer, cursor);
+ }
+
+
+ // non-javadoc, see interface HeaderValueParser
+ public HeaderElement[] parseElements(final CharArrayBuffer buffer,
+ final ParserCursor cursor) {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ final List<HeaderElement> elements = new ArrayList<HeaderElement>();
+ while (!cursor.atEnd()) {
+ final HeaderElement element = parseHeaderElement(buffer, cursor);
+ if (!(element.getName().length() == 0 && element.getValue() == null)) {
+ elements.add(element);
+ }
+ }
+ return elements.toArray(new HeaderElement[elements.size()]);
+ }
+
+
+ /**
+ * Parses an element with the given parser.
+ *
+ * @param value the header element to parse
+ * @param parser the parser to use, or <code>null</code> for default
+ *
+ * @return the parsed header element
+ */
+ public static
+ HeaderElement parseHeaderElement(final String value,
+ final HeaderValueParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ final ParserCursor cursor = new ParserCursor(0, value.length());
+ return (parser != null ? parser : BasicHeaderValueParser.INSTANCE)
+ .parseHeaderElement(buffer, cursor);
+ }
+
+
+ // non-javadoc, see interface HeaderValueParser
+ public HeaderElement parseHeaderElement(final CharArrayBuffer buffer,
+ final ParserCursor cursor) {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ final NameValuePair nvp = parseNameValuePair(buffer, cursor);
+ NameValuePair[] params = null;
+ if (!cursor.atEnd()) {
+ final char ch = buffer.charAt(cursor.getPos() - 1);
+ if (ch != ELEM_DELIMITER) {
+ params = parseParameters(buffer, cursor);
+ }
+ }
+ return createHeaderElement(nvp.getName(), nvp.getValue(), params);
+ }
+
+
+ /**
+ * Creates a header element.
+ * Called from {@link #parseHeaderElement}.
+ *
+ * @return a header element representing the argument
+ */
+ protected HeaderElement createHeaderElement(
+ final String name,
+ final String value,
+ final NameValuePair[] params) {
+ return new BasicHeaderElement(name, value, params);
+ }
+
+
+ /**
+ * Parses parameters with the given parser.
+ *
+ * @param value the parameter list to parse
+ * @param parser the parser to use, or <code>null</code> for default
+ *
+ * @return array holding the parameters, never <code>null</code>
+ */
+ public static
+ NameValuePair[] parseParameters(final String value,
+ final HeaderValueParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ final ParserCursor cursor = new ParserCursor(0, value.length());
+ return (parser != null ? parser : BasicHeaderValueParser.INSTANCE)
+ .parseParameters(buffer, cursor);
+ }
+
+
+
+ // non-javadoc, see interface HeaderValueParser
+ public NameValuePair[] parseParameters(final CharArrayBuffer buffer,
+ final ParserCursor cursor) {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ int pos = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+
+ while (pos < indexTo) {
+ final char ch = buffer.charAt(pos);
+ if (HTTP.isWhitespace(ch)) {
+ pos++;
+ } else {
+ break;
+ }
+ }
+ cursor.updatePos(pos);
+ if (cursor.atEnd()) {
+ return new NameValuePair[] {};
+ }
+
+ final List<NameValuePair> params = new ArrayList<NameValuePair>();
+ while (!cursor.atEnd()) {
+ final NameValuePair param = parseNameValuePair(buffer, cursor);
+ params.add(param);
+ final char ch = buffer.charAt(cursor.getPos() - 1);
+ if (ch == ELEM_DELIMITER) {
+ break;
+ }
+ }
+
+ return params.toArray(new NameValuePair[params.size()]);
+ }
+
+ /**
+ * Parses a name-value-pair with the given parser.
+ *
+ * @param value the NVP to parse
+ * @param parser the parser to use, or <code>null</code> for default
+ *
+ * @return the parsed name-value pair
+ */
+ public static
+ NameValuePair parseNameValuePair(final String value,
+ final HeaderValueParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ final ParserCursor cursor = new ParserCursor(0, value.length());
+ return (parser != null ? parser : BasicHeaderValueParser.INSTANCE)
+ .parseNameValuePair(buffer, cursor);
+ }
+
+
+ // non-javadoc, see interface HeaderValueParser
+ public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
+ final ParserCursor cursor) {
+ return parseNameValuePair(buffer, cursor, ALL_DELIMITERS);
+ }
+
+ private static boolean isOneOf(final char ch, final char[] chs) {
+ if (chs != null) {
+ for (final char ch2 : chs) {
+ if (ch == ch2) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
+ final ParserCursor cursor,
+ final char[] delimiters) {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+
+ boolean terminated = false;
+
+ int pos = cursor.getPos();
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+
+ // Find name
+ final String name;
+ while (pos < indexTo) {
+ final char ch = buffer.charAt(pos);
+ if (ch == '=') {
+ break;
+ }
+ if (isOneOf(ch, delimiters)) {
+ terminated = true;
+ break;
+ }
+ pos++;
+ }
+
+ if (pos == indexTo) {
+ terminated = true;
+ name = buffer.substringTrimmed(indexFrom, indexTo);
+ } else {
+ name = buffer.substringTrimmed(indexFrom, pos);
+ pos++;
+ }
+
+ if (terminated) {
+ cursor.updatePos(pos);
+ return createNameValuePair(name, null);
+ }
+
+ // Find value
+ final String value;
+ int i1 = pos;
+
+ boolean qouted = false;
+ boolean escaped = false;
+ while (pos < indexTo) {
+ final char ch = buffer.charAt(pos);
+ if (ch == '"' && !escaped) {
+ qouted = !qouted;
+ }
+ if (!qouted && !escaped && isOneOf(ch, delimiters)) {
+ terminated = true;
+ break;
+ }
+ if (escaped) {
+ escaped = false;
+ } else {
+ escaped = qouted && ch == '\\';
+ }
+ pos++;
+ }
+
+ int i2 = pos;
+ // Trim leading white spaces
+ while (i1 < i2 && (HTTP.isWhitespace(buffer.charAt(i1)))) {
+ i1++;
+ }
+ // Trim trailing white spaces
+ while ((i2 > i1) && (HTTP.isWhitespace(buffer.charAt(i2 - 1)))) {
+ i2--;
+ }
+ // Strip away quotes if necessary
+ if (((i2 - i1) >= 2)
+ && (buffer.charAt(i1) == '"')
+ && (buffer.charAt(i2 - 1) == '"')) {
+ i1++;
+ i2--;
+ }
+ value = buffer.substring(i1, i2);
+ if (terminated) {
+ pos++;
+ }
+ cursor.updatePos(pos);
+ return createNameValuePair(name, value);
+ }
+
+ /**
+ * Creates a name-value pair.
+ * Called from {@link #parseNameValuePair}.
+ *
+ * @param name the name
+ * @param value the value, or <code>null</code>
+ *
+ * @return a name-value pair representing the arguments
+ */
+ protected NameValuePair createNameValuePair(final String name, final String value) {
+ return new BasicNameValuePair(name, value);
+ }
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java
new file mode 100644
index 000000000..fcb560ccd
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * Basic implementation of {@link HttpEntityEnclosingRequest}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicHttpEntityEnclosingRequest
+ extends BasicHttpRequest implements HttpEntityEnclosingRequest {
+
+ private HttpEntity entity;
+
+ public BasicHttpEntityEnclosingRequest(final String method, final String uri) {
+ super(method, uri);
+ }
+
+ public BasicHttpEntityEnclosingRequest(final String method, final String uri,
+ final ProtocolVersion ver) {
+ super(method, uri, ver);
+ }
+
+ public BasicHttpEntityEnclosingRequest(final RequestLine requestline) {
+ super(requestline);
+ }
+
+ public HttpEntity getEntity() {
+ return this.entity;
+ }
+
+ public void setEntity(final HttpEntity entity) {
+ this.entity = entity;
+ }
+
+ public boolean expectContinue() {
+ final Header expect = getFirstHeader(HTTP.EXPECT_DIRECTIVE);
+ return expect != null && HTTP.EXPECT_CONTINUE.equalsIgnoreCase(expect.getValue());
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpRequest.java
new file mode 100644
index 000000000..be795a08e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpRequest.java
@@ -0,0 +1,114 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of {@link HttpRequest}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicHttpRequest extends AbstractHttpMessage implements HttpRequest {
+
+ private final String method;
+ private final String uri;
+
+ private RequestLine requestline;
+
+ /**
+ * Creates an instance of this class using the given request method
+ * and URI.
+ *
+ * @param method request method.
+ * @param uri request URI.
+ */
+ public BasicHttpRequest(final String method, final String uri) {
+ super();
+ this.method = Args.notNull(method, "Method name");
+ this.uri = Args.notNull(uri, "Request URI");
+ this.requestline = null;
+ }
+
+ /**
+ * Creates an instance of this class using the given request method, URI
+ * and the HTTP protocol version.
+ *
+ * @param method request method.
+ * @param uri request URI.
+ * @param ver HTTP protocol version.
+ */
+ public BasicHttpRequest(final String method, final String uri, final ProtocolVersion ver) {
+ this(new BasicRequestLine(method, uri, ver));
+ }
+
+ /**
+ * Creates an instance of this class using the given request line.
+ *
+ * @param requestline request line.
+ */
+ public BasicHttpRequest(final RequestLine requestline) {
+ super();
+ this.requestline = Args.notNull(requestline, "Request line");
+ this.method = requestline.getMethod();
+ this.uri = requestline.getUri();
+ }
+
+ /**
+ * Returns the HTTP protocol version to be used for this request.
+ *
+ * @see #BasicHttpRequest(String, String)
+ */
+ public ProtocolVersion getProtocolVersion() {
+ return getRequestLine().getProtocolVersion();
+ }
+
+ /**
+ * Returns the request line of this request.
+ *
+ * @see #BasicHttpRequest(String, String)
+ */
+ public RequestLine getRequestLine() {
+ if (this.requestline == null) {
+ this.requestline = new BasicRequestLine(this.method, this.uri, HttpVersion.HTTP_1_1);
+ }
+ return this.requestline;
+ }
+
+ @Override
+ public String toString() {
+ return this.method + " " + this.uri + " " + this.headergroup;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpResponse.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpResponse.java
new file mode 100644
index 000000000..f16b1ca59
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicHttpResponse.java
@@ -0,0 +1,218 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.ReasonPhraseCatalog;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of {@link HttpResponse}.
+ *
+ * @see ch.boye.httpclientandroidlib.impl.DefaultHttpResponseFactory
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicHttpResponse extends AbstractHttpMessage implements HttpResponse {
+
+ private StatusLine statusline;
+ private ProtocolVersion ver;
+ private int code;
+ private String reasonPhrase;
+ private HttpEntity entity;
+ private final ReasonPhraseCatalog reasonCatalog;
+ private Locale locale;
+
+ /**
+ * Creates a new response.
+ * This is the constructor to which all others map.
+ *
+ * @param statusline the status line
+ * @param catalog the reason phrase catalog, or
+ * <code>null</code> to disable automatic
+ * reason phrase lookup
+ * @param locale the locale for looking up reason phrases, or
+ * <code>null</code> for the system locale
+ */
+ public BasicHttpResponse(final StatusLine statusline,
+ final ReasonPhraseCatalog catalog,
+ final Locale locale) {
+ super();
+ this.statusline = Args.notNull(statusline, "Status line");
+ this.ver = statusline.getProtocolVersion();
+ this.code = statusline.getStatusCode();
+ this.reasonPhrase = statusline.getReasonPhrase();
+ this.reasonCatalog = catalog;
+ this.locale = locale;
+ }
+
+ /**
+ * Creates a response from a status line.
+ * The response will not have a reason phrase catalog and
+ * use the system default locale.
+ *
+ * @param statusline the status line
+ */
+ public BasicHttpResponse(final StatusLine statusline) {
+ super();
+ this.statusline = Args.notNull(statusline, "Status line");
+ this.ver = statusline.getProtocolVersion();
+ this.code = statusline.getStatusCode();
+ this.reasonPhrase = statusline.getReasonPhrase();
+ this.reasonCatalog = null;
+ this.locale = null;
+ }
+
+ /**
+ * Creates a response from elements of a status line.
+ * The response will not have a reason phrase catalog and
+ * use the system default locale.
+ *
+ * @param ver the protocol version of the response
+ * @param code the status code of the response
+ * @param reason the reason phrase to the status code, or
+ * <code>null</code>
+ */
+ public BasicHttpResponse(final ProtocolVersion ver,
+ final int code,
+ final String reason) {
+ super();
+ Args.notNegative(code, "Status code");
+ this.statusline = null;
+ this.ver = ver;
+ this.code = code;
+ this.reasonPhrase = reason;
+ this.reasonCatalog = null;
+ this.locale = null;
+ }
+
+
+ // non-javadoc, see interface HttpMessage
+ public ProtocolVersion getProtocolVersion() {
+ return this.ver;
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public StatusLine getStatusLine() {
+ if (this.statusline == null) {
+ this.statusline = new BasicStatusLine(
+ this.ver != null ? this.ver : HttpVersion.HTTP_1_1,
+ this.code,
+ this.reasonPhrase != null ? this.reasonPhrase : getReason(this.code));
+ }
+ return this.statusline;
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public HttpEntity getEntity() {
+ return this.entity;
+ }
+
+ public Locale getLocale() {
+ return this.locale;
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public void setStatusLine(final StatusLine statusline) {
+ this.statusline = Args.notNull(statusline, "Status line");
+ this.ver = statusline.getProtocolVersion();
+ this.code = statusline.getStatusCode();
+ this.reasonPhrase = statusline.getReasonPhrase();
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public void setStatusLine(final ProtocolVersion ver, final int code) {
+ Args.notNegative(code, "Status code");
+ this.statusline = null;
+ this.ver = ver;
+ this.code = code;
+ this.reasonPhrase = null;
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public void setStatusLine(
+ final ProtocolVersion ver, final int code, final String reason) {
+ Args.notNegative(code, "Status code");
+ this.statusline = null;
+ this.ver = ver;
+ this.code = code;
+ this.reasonPhrase = reason;
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public void setStatusCode(final int code) {
+ Args.notNegative(code, "Status code");
+ this.statusline = null;
+ this.code = code;
+ this.reasonPhrase = null;
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public void setReasonPhrase(final String reason) {
+ this.statusline = null;
+ this.reasonPhrase = reason;
+ }
+
+ // non-javadoc, see interface HttpResponse
+ public void setEntity(final HttpEntity entity) {
+ this.entity = entity;
+ }
+
+ public void setLocale(final Locale locale) {
+ this.locale = Args.notNull(locale, "Locale");
+ this.statusline = null;
+ }
+
+ /**
+ * Looks up a reason phrase.
+ * This method evaluates the currently set catalog and locale.
+ * It also handles a missing catalog.
+ *
+ * @param code the status code for which to look up the reason
+ *
+ * @return the reason phrase, or <code>null</code> if there is none
+ */
+ protected String getReason(final int code) {
+ return this.reasonCatalog != null ? this.reasonCatalog.getReason(code,
+ this.locale != null ? this.locale : Locale.getDefault()) : null;
+ }
+
+ @Override
+ public String toString() {
+ return getStatusLine() + " " + this.headergroup;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineFormatter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineFormatter.java
new file mode 100644
index 000000000..6eabfd48f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineFormatter.java
@@ -0,0 +1,319 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Interface for formatting elements of the HEAD section of an HTTP message.
+ * This is the complement to {@link LineParser}.
+ * There are individual methods for formatting a request line, a
+ * status line, or a header line. The formatting does <i>not</i> include the
+ * trailing line break sequence CR-LF.
+ * The formatted lines are returned in memory, the formatter does not depend
+ * on any specific IO mechanism.
+ * Instances of this interface are expected to be stateless and thread-safe.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicLineFormatter implements LineFormatter {
+
+ /**
+ * A default instance of this class, for use as default or fallback.
+ * Note that {@link BasicLineFormatter} is not a singleton, there can
+ * be many instances of the class itself and of derived classes.
+ * The instance here provides non-customized, default behavior.
+ *
+ * @deprecated (4.3) use {@link #INSTANCE}
+ */
+ @Deprecated
+ public final static BasicLineFormatter DEFAULT = new BasicLineFormatter();
+
+ public final static BasicLineFormatter INSTANCE = new BasicLineFormatter();
+
+ public BasicLineFormatter() {
+ super();
+ }
+
+ /**
+ * Obtains a buffer for formatting.
+ *
+ * @param charBuffer a buffer already available, or <code>null</code>
+ *
+ * @return the cleared argument buffer if there is one, or
+ * a new empty buffer that can be used for formatting
+ */
+ protected CharArrayBuffer initBuffer(final CharArrayBuffer charBuffer) {
+ CharArrayBuffer buffer = charBuffer;
+ if (buffer != null) {
+ buffer.clear();
+ } else {
+ buffer = new CharArrayBuffer(64);
+ }
+ return buffer;
+ }
+
+
+ /**
+ * Formats a protocol version.
+ *
+ * @param version the protocol version to format
+ * @param formatter the formatter to use, or
+ * <code>null</code> for the
+ * {@link #INSTANCE default}
+ *
+ * @return the formatted protocol version
+ */
+ public static
+ String formatProtocolVersion(final ProtocolVersion version,
+ final LineFormatter formatter) {
+ return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
+ .appendProtocolVersion(null, version).toString();
+ }
+
+
+ // non-javadoc, see interface LineFormatter
+ public CharArrayBuffer appendProtocolVersion(final CharArrayBuffer buffer,
+ final ProtocolVersion version) {
+ Args.notNull(version, "Protocol version");
+ // can't use initBuffer, that would clear the argument!
+ CharArrayBuffer result = buffer;
+ final int len = estimateProtocolVersionLen(version);
+ if (result == null) {
+ result = new CharArrayBuffer(len);
+ } else {
+ result.ensureCapacity(len);
+ }
+
+ result.append(version.getProtocol());
+ result.append('/');
+ result.append(Integer.toString(version.getMajor()));
+ result.append('.');
+ result.append(Integer.toString(version.getMinor()));
+
+ return result;
+ }
+
+
+ /**
+ * Guesses the length of a formatted protocol version.
+ * Needed to guess the length of a formatted request or status line.
+ *
+ * @param version the protocol version to format, or <code>null</code>
+ *
+ * @return the estimated length of the formatted protocol version,
+ * in characters
+ */
+ protected int estimateProtocolVersionLen(final ProtocolVersion version) {
+ return version.getProtocol().length() + 4; // room for "HTTP/1.1"
+ }
+
+
+ /**
+ * Formats a request line.
+ *
+ * @param reqline the request line to format
+ * @param formatter the formatter to use, or
+ * <code>null</code> for the
+ * {@link #INSTANCE default}
+ *
+ * @return the formatted request line
+ */
+ public static String formatRequestLine(final RequestLine reqline,
+ final LineFormatter formatter) {
+ return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
+ .formatRequestLine(null, reqline).toString();
+ }
+
+
+ // non-javadoc, see interface LineFormatter
+ public CharArrayBuffer formatRequestLine(final CharArrayBuffer buffer,
+ final RequestLine reqline) {
+ Args.notNull(reqline, "Request line");
+ final CharArrayBuffer result = initBuffer(buffer);
+ doFormatRequestLine(result, reqline);
+
+ return result;
+ }
+
+
+ /**
+ * Actually formats a request line.
+ * Called from {@link #formatRequestLine}.
+ *
+ * @param buffer the empty buffer into which to format,
+ * never <code>null</code>
+ * @param reqline the request line to format, never <code>null</code>
+ */
+ protected void doFormatRequestLine(final CharArrayBuffer buffer,
+ final RequestLine reqline) {
+ final String method = reqline.getMethod();
+ final String uri = reqline.getUri();
+
+ // room for "GET /index.html HTTP/1.1"
+ final int len = method.length() + 1 + uri.length() + 1 +
+ estimateProtocolVersionLen(reqline.getProtocolVersion());
+ buffer.ensureCapacity(len);
+
+ buffer.append(method);
+ buffer.append(' ');
+ buffer.append(uri);
+ buffer.append(' ');
+ appendProtocolVersion(buffer, reqline.getProtocolVersion());
+ }
+
+
+
+ /**
+ * Formats a status line.
+ *
+ * @param statline the status line to format
+ * @param formatter the formatter to use, or
+ * <code>null</code> for the
+ * {@link #INSTANCE default}
+ *
+ * @return the formatted status line
+ */
+ public static String formatStatusLine(final StatusLine statline,
+ final LineFormatter formatter) {
+ return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
+ .formatStatusLine(null, statline).toString();
+ }
+
+
+ // non-javadoc, see interface LineFormatter
+ public CharArrayBuffer formatStatusLine(final CharArrayBuffer buffer,
+ final StatusLine statline) {
+ Args.notNull(statline, "Status line");
+ final CharArrayBuffer result = initBuffer(buffer);
+ doFormatStatusLine(result, statline);
+
+ return result;
+ }
+
+
+ /**
+ * Actually formats a status line.
+ * Called from {@link #formatStatusLine}.
+ *
+ * @param buffer the empty buffer into which to format,
+ * never <code>null</code>
+ * @param statline the status line to format, never <code>null</code>
+ */
+ protected void doFormatStatusLine(final CharArrayBuffer buffer,
+ final StatusLine statline) {
+
+ int len = estimateProtocolVersionLen(statline.getProtocolVersion())
+ + 1 + 3 + 1; // room for "HTTP/1.1 200 "
+ final String reason = statline.getReasonPhrase();
+ if (reason != null) {
+ len += reason.length();
+ }
+ buffer.ensureCapacity(len);
+
+ appendProtocolVersion(buffer, statline.getProtocolVersion());
+ buffer.append(' ');
+ buffer.append(Integer.toString(statline.getStatusCode()));
+ buffer.append(' '); // keep whitespace even if reason phrase is empty
+ if (reason != null) {
+ buffer.append(reason);
+ }
+ }
+
+
+ /**
+ * Formats a header.
+ *
+ * @param header the header to format
+ * @param formatter the formatter to use, or
+ * <code>null</code> for the
+ * {@link #INSTANCE default}
+ *
+ * @return the formatted header
+ */
+ public static String formatHeader(final Header header,
+ final LineFormatter formatter) {
+ return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
+ .formatHeader(null, header).toString();
+ }
+
+
+ // non-javadoc, see interface LineFormatter
+ public CharArrayBuffer formatHeader(final CharArrayBuffer buffer,
+ final Header header) {
+ Args.notNull(header, "Header");
+ final CharArrayBuffer result;
+
+ if (header instanceof FormattedHeader) {
+ // If the header is backed by a buffer, re-use the buffer
+ result = ((FormattedHeader)header).getBuffer();
+ } else {
+ result = initBuffer(buffer);
+ doFormatHeader(result, header);
+ }
+ return result;
+
+ } // formatHeader
+
+
+ /**
+ * Actually formats a header.
+ * Called from {@link #formatHeader}.
+ *
+ * @param buffer the empty buffer into which to format,
+ * never <code>null</code>
+ * @param header the header to format, never <code>null</code>
+ */
+ protected void doFormatHeader(final CharArrayBuffer buffer,
+ final Header header) {
+ final String name = header.getName();
+ final String value = header.getValue();
+
+ int len = name.length() + 2;
+ if (value != null) {
+ len += value.length();
+ }
+ buffer.ensureCapacity(len);
+
+ buffer.append(name);
+ buffer.append(": ");
+ if (value != null) {
+ buffer.append(value);
+ }
+ }
+
+
+} // class BasicLineFormatter
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineParser.java
new file mode 100644
index 000000000..dabde0f62
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicLineParser.java
@@ -0,0 +1,456 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Basic parser for lines in the head section of an HTTP message.
+ * There are individual methods for parsing a request line, a
+ * status line, or a header line.
+ * The lines to parse are passed in memory, the parser does not depend
+ * on any specific IO mechanism.
+ * Instances of this class are stateless and thread-safe.
+ * Derived classes MUST maintain these properties.
+ *
+ * <p>
+ * Note: This class was created by refactoring parsing code located in
+ * various other classes. The author tags from those other classes have
+ * been replicated here, although the association with the parsing code
+ * taken from there has not been traced.
+ * </p>
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicLineParser implements LineParser {
+
+ /**
+ * A default instance of this class, for use as default or fallback.
+ * Note that {@link BasicLineParser} is not a singleton, there can
+ * be many instances of the class itself and of derived classes.
+ * The instance here provides non-customized, default behavior.
+ *
+ * @deprecated (4.3) use {@link #INSTANCE}
+ */
+ @Deprecated
+ public final static BasicLineParser DEFAULT = new BasicLineParser();
+
+ public final static BasicLineParser INSTANCE = new BasicLineParser();
+
+ /**
+ * A version of the protocol to parse.
+ * The version is typically not relevant, but the protocol name.
+ */
+ protected final ProtocolVersion protocol;
+
+
+ /**
+ * Creates a new line parser for the given HTTP-like protocol.
+ *
+ * @param proto a version of the protocol to parse, or
+ * <code>null</code> for HTTP. The actual version
+ * is not relevant, only the protocol name.
+ */
+ public BasicLineParser(final ProtocolVersion proto) {
+ this.protocol = proto != null? proto : HttpVersion.HTTP_1_1;
+ }
+
+
+ /**
+ * Creates a new line parser for HTTP.
+ */
+ public BasicLineParser() {
+ this(null);
+ }
+
+
+ public static
+ ProtocolVersion parseProtocolVersion(final String value,
+ final LineParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ final ParserCursor cursor = new ParserCursor(0, value.length());
+ return (parser != null ? parser : BasicLineParser.INSTANCE)
+ .parseProtocolVersion(buffer, cursor);
+ }
+
+
+ // non-javadoc, see interface LineParser
+ public ProtocolVersion parseProtocolVersion(final CharArrayBuffer buffer,
+ final ParserCursor cursor) throws ParseException {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ final String protoname = this.protocol.getProtocol();
+ final int protolength = protoname.length();
+
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+
+ skipWhitespace(buffer, cursor);
+
+ int i = cursor.getPos();
+
+ // long enough for "HTTP/1.1"?
+ if (i + protolength + 4 > indexTo) {
+ throw new ParseException
+ ("Not a valid protocol version: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+
+ // check the protocol name and slash
+ boolean ok = true;
+ for (int j=0; ok && (j<protolength); j++) {
+ ok = (buffer.charAt(i+j) == protoname.charAt(j));
+ }
+ if (ok) {
+ ok = (buffer.charAt(i+protolength) == '/');
+ }
+ if (!ok) {
+ throw new ParseException
+ ("Not a valid protocol version: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+
+ i += protolength+1;
+
+ final int period = buffer.indexOf('.', i, indexTo);
+ if (period == -1) {
+ throw new ParseException
+ ("Invalid protocol version number: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+ final int major;
+ try {
+ major = Integer.parseInt(buffer.substringTrimmed(i, period));
+ } catch (final NumberFormatException e) {
+ throw new ParseException
+ ("Invalid protocol major version number: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+ i = period + 1;
+
+ int blank = buffer.indexOf(' ', i, indexTo);
+ if (blank == -1) {
+ blank = indexTo;
+ }
+ final int minor;
+ try {
+ minor = Integer.parseInt(buffer.substringTrimmed(i, blank));
+ } catch (final NumberFormatException e) {
+ throw new ParseException(
+ "Invalid protocol minor version number: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+
+ cursor.updatePos(blank);
+
+ return createProtocolVersion(major, minor);
+
+ } // parseProtocolVersion
+
+
+ /**
+ * Creates a protocol version.
+ * Called from {@link #parseProtocolVersion}.
+ *
+ * @param major the major version number, for example 1 in HTTP/1.0
+ * @param minor the minor version number, for example 0 in HTTP/1.0
+ *
+ * @return the protocol version
+ */
+ protected ProtocolVersion createProtocolVersion(final int major, final int minor) {
+ return protocol.forVersion(major, minor);
+ }
+
+
+
+ // non-javadoc, see interface LineParser
+ public boolean hasProtocolVersion(final CharArrayBuffer buffer,
+ final ParserCursor cursor) {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ int index = cursor.getPos();
+
+ final String protoname = this.protocol.getProtocol();
+ final int protolength = protoname.length();
+
+ if (buffer.length() < protolength+4)
+ {
+ return false; // not long enough for "HTTP/1.1"
+ }
+
+ if (index < 0) {
+ // end of line, no tolerance for trailing whitespace
+ // this works only for single-digit major and minor version
+ index = buffer.length() -4 -protolength;
+ } else if (index == 0) {
+ // beginning of line, tolerate leading whitespace
+ while ((index < buffer.length()) &&
+ HTTP.isWhitespace(buffer.charAt(index))) {
+ index++;
+ }
+ } // else within line, don't tolerate whitespace
+
+
+ if (index + protolength + 4 > buffer.length()) {
+ return false;
+ }
+
+
+ // just check protocol name and slash, no need to analyse the version
+ boolean ok = true;
+ for (int j=0; ok && (j<protolength); j++) {
+ ok = (buffer.charAt(index+j) == protoname.charAt(j));
+ }
+ if (ok) {
+ ok = (buffer.charAt(index+protolength) == '/');
+ }
+
+ return ok;
+ }
+
+
+
+ public static
+ RequestLine parseRequestLine(final String value,
+ final LineParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ final ParserCursor cursor = new ParserCursor(0, value.length());
+ return (parser != null ? parser : BasicLineParser.INSTANCE)
+ .parseRequestLine(buffer, cursor);
+ }
+
+
+ /**
+ * Parses a request line.
+ *
+ * @param buffer a buffer holding the line to parse
+ *
+ * @return the parsed request line
+ *
+ * @throws ParseException in case of a parse error
+ */
+ public RequestLine parseRequestLine(final CharArrayBuffer buffer,
+ final ParserCursor cursor) throws ParseException {
+
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+
+ try {
+ skipWhitespace(buffer, cursor);
+ int i = cursor.getPos();
+
+ int blank = buffer.indexOf(' ', i, indexTo);
+ if (blank < 0) {
+ throw new ParseException("Invalid request line: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+ final String method = buffer.substringTrimmed(i, blank);
+ cursor.updatePos(blank);
+
+ skipWhitespace(buffer, cursor);
+ i = cursor.getPos();
+
+ blank = buffer.indexOf(' ', i, indexTo);
+ if (blank < 0) {
+ throw new ParseException("Invalid request line: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+ final String uri = buffer.substringTrimmed(i, blank);
+ cursor.updatePos(blank);
+
+ final ProtocolVersion ver = parseProtocolVersion(buffer, cursor);
+
+ skipWhitespace(buffer, cursor);
+ if (!cursor.atEnd()) {
+ throw new ParseException("Invalid request line: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+
+ return createRequestLine(method, uri, ver);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ParseException("Invalid request line: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+ } // parseRequestLine
+
+
+ /**
+ * Instantiates a new request line.
+ * Called from {@link #parseRequestLine}.
+ *
+ * @param method the request method
+ * @param uri the requested URI
+ * @param ver the protocol version
+ *
+ * @return a new status line with the given data
+ */
+ protected RequestLine createRequestLine(final String method,
+ final String uri,
+ final ProtocolVersion ver) {
+ return new BasicRequestLine(method, uri, ver);
+ }
+
+
+
+ public static
+ StatusLine parseStatusLine(final String value,
+ final LineParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ final ParserCursor cursor = new ParserCursor(0, value.length());
+ return (parser != null ? parser : BasicLineParser.INSTANCE)
+ .parseStatusLine(buffer, cursor);
+ }
+
+
+ // non-javadoc, see interface LineParser
+ public StatusLine parseStatusLine(final CharArrayBuffer buffer,
+ final ParserCursor cursor) throws ParseException {
+ Args.notNull(buffer, "Char array buffer");
+ Args.notNull(cursor, "Parser cursor");
+ final int indexFrom = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+
+ try {
+ // handle the HTTP-Version
+ final ProtocolVersion ver = parseProtocolVersion(buffer, cursor);
+
+ // handle the Status-Code
+ skipWhitespace(buffer, cursor);
+ int i = cursor.getPos();
+
+ int blank = buffer.indexOf(' ', i, indexTo);
+ if (blank < 0) {
+ blank = indexTo;
+ }
+ final int statusCode;
+ final String s = buffer.substringTrimmed(i, blank);
+ for (int j = 0; j < s.length(); j++) {
+ if (!Character.isDigit(s.charAt(j))) {
+ throw new ParseException(
+ "Status line contains invalid status code: "
+ + buffer.substring(indexFrom, indexTo));
+ }
+ }
+ try {
+ statusCode = Integer.parseInt(s);
+ } catch (final NumberFormatException e) {
+ throw new ParseException(
+ "Status line contains invalid status code: "
+ + buffer.substring(indexFrom, indexTo));
+ }
+ //handle the Reason-Phrase
+ i = blank;
+ final String reasonPhrase;
+ if (i < indexTo) {
+ reasonPhrase = buffer.substringTrimmed(i, indexTo);
+ } else {
+ reasonPhrase = "";
+ }
+ return createStatusLine(ver, statusCode, reasonPhrase);
+
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ParseException("Invalid status line: " +
+ buffer.substring(indexFrom, indexTo));
+ }
+ } // parseStatusLine
+
+
+ /**
+ * Instantiates a new status line.
+ * Called from {@link #parseStatusLine}.
+ *
+ * @param ver the protocol version
+ * @param status the status code
+ * @param reason the reason phrase
+ *
+ * @return a new status line with the given data
+ */
+ protected StatusLine createStatusLine(final ProtocolVersion ver,
+ final int status,
+ final String reason) {
+ return new BasicStatusLine(ver, status, reason);
+ }
+
+
+
+ public static
+ Header parseHeader(final String value,
+ final LineParser parser) throws ParseException {
+ Args.notNull(value, "Value");
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(value.length());
+ buffer.append(value);
+ return (parser != null ? parser : BasicLineParser.INSTANCE)
+ .parseHeader(buffer);
+ }
+
+
+ // non-javadoc, see interface LineParser
+ public Header parseHeader(final CharArrayBuffer buffer)
+ throws ParseException {
+
+ // the actual parser code is in the constructor of BufferedHeader
+ return new BufferedHeader(buffer);
+ }
+
+
+ /**
+ * Helper to skip whitespace.
+ */
+ protected void skipWhitespace(final CharArrayBuffer buffer, final ParserCursor cursor) {
+ int pos = cursor.getPos();
+ final int indexTo = cursor.getUpperBound();
+ while ((pos < indexTo) &&
+ HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ cursor.updatePos(pos);
+ }
+
+} // class BasicLineParser
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicListHeaderIterator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicListHeaderIterator.java
new file mode 100644
index 000000000..ce9db2657
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicListHeaderIterator.java
@@ -0,0 +1,190 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Implementation of a {@link HeaderIterator} based on a {@link List}.
+ * For use by {@link HeaderGroup}.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicListHeaderIterator implements HeaderIterator {
+
+ /**
+ * A list of headers to iterate over.
+ * Not all elements of this array are necessarily part of the iteration.
+ */
+ protected final List<Header> allHeaders;
+
+
+ /**
+ * The position of the next header in {@link #allHeaders allHeaders}.
+ * Negative if the iteration is over.
+ */
+ protected int currentIndex;
+
+
+ /**
+ * The position of the last returned header.
+ * Negative if none has been returned so far.
+ */
+ protected int lastIndex;
+
+
+ /**
+ * The header name to filter by.
+ * <code>null</code> to iterate over all headers in the array.
+ */
+ protected String headerName;
+
+
+
+ /**
+ * Creates a new header iterator.
+ *
+ * @param headers a list of headers over which to iterate
+ * @param name the name of the headers over which to iterate, or
+ * <code>null</code> for any
+ */
+ public BasicListHeaderIterator(final List<Header> headers, final String name) {
+ super();
+ this.allHeaders = Args.notNull(headers, "Header list");
+ this.headerName = name;
+ this.currentIndex = findNext(-1);
+ this.lastIndex = -1;
+ }
+
+
+ /**
+ * Determines the index of the next header.
+ *
+ * @param pos one less than the index to consider first,
+ * -1 to search for the first header
+ *
+ * @return the index of the next header that matches the filter name,
+ * or negative if there are no more headers
+ */
+ protected int findNext(final int pos) {
+ int from = pos;
+ if (from < -1) {
+ return -1;
+ }
+
+ final int to = this.allHeaders.size()-1;
+ boolean found = false;
+ while (!found && (from < to)) {
+ from++;
+ found = filterHeader(from);
+ }
+ return found ? from : -1;
+ }
+
+
+ /**
+ * Checks whether a header is part of the iteration.
+ *
+ * @param index the index of the header to check
+ *
+ * @return <code>true</code> if the header should be part of the
+ * iteration, <code>false</code> to skip
+ */
+ protected boolean filterHeader(final int index) {
+ if (this.headerName == null) {
+ return true;
+ }
+
+ // non-header elements, including null, will trigger exceptions
+ final String name = (this.allHeaders.get(index)).getName();
+
+ return this.headerName.equalsIgnoreCase(name);
+ }
+
+
+ // non-javadoc, see interface HeaderIterator
+ public boolean hasNext() {
+ return (this.currentIndex >= 0);
+ }
+
+
+ /**
+ * Obtains the next header from this iteration.
+ *
+ * @return the next header in this iteration
+ *
+ * @throws NoSuchElementException if there are no more headers
+ */
+ public Header nextHeader()
+ throws NoSuchElementException {
+
+ final int current = this.currentIndex;
+ if (current < 0) {
+ throw new NoSuchElementException("Iteration already finished.");
+ }
+
+ this.lastIndex = current;
+ this.currentIndex = findNext(current);
+
+ return this.allHeaders.get(current);
+ }
+
+
+ /**
+ * Returns the next header.
+ * Same as {@link #nextHeader nextHeader}, but not type-safe.
+ *
+ * @return the next header in this iteration
+ *
+ * @throws NoSuchElementException if there are no more headers
+ */
+ public final Object next()
+ throws NoSuchElementException {
+ return nextHeader();
+ }
+
+
+ /**
+ * Removes the header that was returned last.
+ */
+ public void remove()
+ throws UnsupportedOperationException {
+ Asserts.check(this.lastIndex >= 0, "No header to remove");
+ this.allHeaders.remove(this.lastIndex);
+ this.lastIndex = -1;
+ this.currentIndex--; // adjust for the removed element
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicNameValuePair.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicNameValuePair.java
new file mode 100644
index 000000000..530e5042e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicNameValuePair.java
@@ -0,0 +1,111 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.LangUtils;
+
+/**
+ * Basic implementation of {@link NameValuePair}.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicNameValuePair implements NameValuePair, Cloneable, Serializable {
+
+ private static final long serialVersionUID = -6437800749411518984L;
+
+ private final String name;
+ private final String value;
+
+ /**
+ * Default Constructor taking a name and a value. The value may be null.
+ *
+ * @param name The name.
+ * @param value The value.
+ */
+ public BasicNameValuePair(final String name, final String value) {
+ super();
+ this.name = Args.notNull(name, "Name");
+ this.value = value;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ // don't call complex default formatting for a simple toString
+
+ if (this.value == null) {
+ return name;
+ }
+ final int len = this.name.length() + 1 + this.value.length();
+ final StringBuilder buffer = new StringBuilder(len);
+ buffer.append(this.name);
+ buffer.append("=");
+ buffer.append(this.value);
+ return buffer.toString();
+ }
+
+ @Override
+ public boolean equals(final Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object instanceof NameValuePair) {
+ final BasicNameValuePair that = (BasicNameValuePair) object;
+ return this.name.equals(that.name)
+ && LangUtils.equals(this.value, that.value);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = LangUtils.HASH_SEED;
+ hash = LangUtils.hashCode(hash, this.name);
+ hash = LangUtils.hashCode(hash, this.value);
+ return hash;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicRequestLine.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicRequestLine.java
new file mode 100644
index 000000000..40c838b12
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicRequestLine.java
@@ -0,0 +1,83 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of {@link RequestLine}.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicRequestLine implements RequestLine, Cloneable, Serializable {
+
+ private static final long serialVersionUID = 2810581718468737193L;
+
+ private final ProtocolVersion protoversion;
+ private final String method;
+ private final String uri;
+
+ public BasicRequestLine(final String method,
+ final String uri,
+ final ProtocolVersion version) {
+ super();
+ this.method = Args.notNull(method, "Method");
+ this.uri = Args.notNull(uri, "URI");
+ this.protoversion = Args.notNull(version, "Version");
+ }
+
+ public String getMethod() {
+ return this.method;
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ return this.protoversion;
+ }
+
+ public String getUri() {
+ return this.uri;
+ }
+
+ @Override
+ public String toString() {
+ // no need for non-default formatting in toString()
+ return BasicLineFormatter.INSTANCE.formatRequestLine(null, this).toString();
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicStatusLine.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicStatusLine.java
new file mode 100644
index 000000000..cce1f25d7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicStatusLine.java
@@ -0,0 +1,100 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of {@link StatusLine}
+ *
+ * @since 4.0
+ */
+@Immutable
+public class BasicStatusLine implements StatusLine, Cloneable, Serializable {
+
+ private static final long serialVersionUID = -2443303766890459269L;
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** The protocol version. */
+ private final ProtocolVersion protoVersion;
+
+ /** The status code. */
+ private final int statusCode;
+
+ /** The reason phrase. */
+ private final String reasonPhrase;
+
+ // ----------------------------------------------------------- Constructors
+ /**
+ * Creates a new status line with the given version, status, and reason.
+ *
+ * @param version the protocol version of the response
+ * @param statusCode the status code of the response
+ * @param reasonPhrase the reason phrase to the status code, or
+ * <code>null</code>
+ */
+ public BasicStatusLine(final ProtocolVersion version, final int statusCode,
+ final String reasonPhrase) {
+ super();
+ this.protoVersion = Args.notNull(version, "Version");
+ this.statusCode = Args.notNegative(statusCode, "Status code");
+ this.reasonPhrase = reasonPhrase;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ public int getStatusCode() {
+ return this.statusCode;
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ return this.protoVersion;
+ }
+
+ public String getReasonPhrase() {
+ return this.reasonPhrase;
+ }
+
+ @Override
+ public String toString() {
+ // no need for non-default formatting in toString()
+ return BasicLineFormatter.INSTANCE.formatStatusLine(null, this).toString();
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicTokenIterator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicTokenIterator.java
new file mode 100644
index 000000000..98bd841b5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BasicTokenIterator.java
@@ -0,0 +1,414 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.util.NoSuchElementException;
+
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.TokenIterator;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Basic implementation of a {@link TokenIterator}.
+ * This implementation parses <tt>#token<tt> sequences as
+ * defined by RFC 2616, section 2.
+ * It extends that definition somewhat beyond US-ASCII.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BasicTokenIterator implements TokenIterator {
+
+ /** The HTTP separator characters. Defined in RFC 2616, section 2.2. */
+ // the order of the characters here is adjusted to put the
+ // most likely candidates at the beginning of the collection
+ public final static String HTTP_SEPARATORS = " ,;=()<>@:\\\"/[]?{}\t";
+
+
+ /** The iterator from which to obtain the next header. */
+ protected final HeaderIterator headerIt;
+
+ /**
+ * The value of the current header.
+ * This is the header value that includes {@link #currentToken}.
+ * Undefined if the iteration is over.
+ */
+ protected String currentHeader;
+
+ /**
+ * The token to be returned by the next call to {@link #nextToken()}.
+ * <code>null</code> if the iteration is over.
+ */
+ protected String currentToken;
+
+ /**
+ * The position after {@link #currentToken} in {@link #currentHeader}.
+ * Undefined if the iteration is over.
+ */
+ protected int searchPos;
+
+
+ /**
+ * Creates a new instance of {@link BasicTokenIterator}.
+ *
+ * @param headerIterator the iterator for the headers to tokenize
+ */
+ public BasicTokenIterator(final HeaderIterator headerIterator) {
+ super();
+ this.headerIt = Args.notNull(headerIterator, "Header iterator");
+ this.searchPos = findNext(-1);
+ }
+
+
+ // non-javadoc, see interface TokenIterator
+ public boolean hasNext() {
+ return (this.currentToken != null);
+ }
+
+
+ /**
+ * Obtains the next token from this iteration.
+ *
+ * @return the next token in this iteration
+ *
+ * @throws NoSuchElementException if the iteration is already over
+ * @throws ParseException if an invalid header value is encountered
+ */
+ public String nextToken()
+ throws NoSuchElementException, ParseException {
+
+ if (this.currentToken == null) {
+ throw new NoSuchElementException("Iteration already finished.");
+ }
+
+ final String result = this.currentToken;
+ // updates currentToken, may trigger ParseException:
+ this.searchPos = findNext(this.searchPos);
+
+ return result;
+ }
+
+
+ /**
+ * Returns the next token.
+ * Same as {@link #nextToken}, but with generic return type.
+ *
+ * @return the next token in this iteration
+ *
+ * @throws NoSuchElementException if there are no more tokens
+ * @throws ParseException if an invalid header value is encountered
+ */
+ public final Object next()
+ throws NoSuchElementException, ParseException {
+ return nextToken();
+ }
+
+
+ /**
+ * Removing tokens is not supported.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public final void remove()
+ throws UnsupportedOperationException {
+
+ throw new UnsupportedOperationException
+ ("Removing tokens is not supported.");
+ }
+
+
+ /**
+ * Determines the next token.
+ * If found, the token is stored in {@link #currentToken}.
+ * The return value indicates the position after the token
+ * in {@link #currentHeader}. If necessary, the next header
+ * will be obtained from {@link #headerIt}.
+ * If not found, {@link #currentToken} is set to <code>null</code>.
+ *
+ * @param pos the position in the current header at which to
+ * start the search, -1 to search in the first header
+ *
+ * @return the position after the found token in the current header, or
+ * negative if there was no next token
+ *
+ * @throws ParseException if an invalid header value is encountered
+ */
+ protected int findNext(final int pos) throws ParseException {
+ int from = pos;
+ if (from < 0) {
+ // called from the constructor, initialize the first header
+ if (!this.headerIt.hasNext()) {
+ return -1;
+ }
+ this.currentHeader = this.headerIt.nextHeader().getValue();
+ from = 0;
+ } else {
+ // called after a token, make sure there is a separator
+ from = findTokenSeparator(from);
+ }
+
+ final int start = findTokenStart(from);
+ if (start < 0) {
+ this.currentToken = null;
+ return -1; // nothing found
+ }
+
+ final int end = findTokenEnd(start);
+ this.currentToken = createToken(this.currentHeader, start, end);
+ return end;
+ }
+
+
+ /**
+ * Creates a new token to be returned.
+ * Called from {@link #findNext findNext} after the token is identified.
+ * The default implementation simply calls
+ * {@link java.lang.String#substring String.substring}.
+ * <br/>
+ * If header values are significantly longer than tokens, and some
+ * tokens are permanently referenced by the application, there can
+ * be problems with garbage collection. A substring will hold a
+ * reference to the full characters of the original string and
+ * therefore occupies more memory than might be expected.
+ * To avoid this, override this method and create a new string
+ * instead of a substring.
+ *
+ * @param value the full header value from which to create a token
+ * @param start the index of the first token character
+ * @param end the index after the last token character
+ *
+ * @return a string representing the token identified by the arguments
+ */
+ protected String createToken(final String value, final int start, final int end) {
+ return value.substring(start, end);
+ }
+
+
+ /**
+ * Determines the starting position of the next token.
+ * This method will iterate over headers if necessary.
+ *
+ * @param pos the position in the current header at which to
+ * start the search
+ *
+ * @return the position of the token start in the current header,
+ * negative if no token start could be found
+ */
+ protected int findTokenStart(final int pos) {
+ int from = Args.notNegative(pos, "Search position");
+ boolean found = false;
+ while (!found && (this.currentHeader != null)) {
+
+ final int to = this.currentHeader.length();
+ while (!found && (from < to)) {
+
+ final char ch = this.currentHeader.charAt(from);
+ if (isTokenSeparator(ch) || isWhitespace(ch)) {
+ // whitspace and token separators are skipped
+ from++;
+ } else if (isTokenChar(this.currentHeader.charAt(from))) {
+ // found the start of a token
+ found = true;
+ } else {
+ throw new ParseException
+ ("Invalid character before token (pos " + from +
+ "): " + this.currentHeader);
+ }
+ }
+ if (!found) {
+ if (this.headerIt.hasNext()) {
+ this.currentHeader = this.headerIt.nextHeader().getValue();
+ from = 0;
+ } else {
+ this.currentHeader = null;
+ }
+ }
+ } // while headers
+
+ return found ? from : -1;
+ }
+
+
+ /**
+ * Determines the position of the next token separator.
+ * Because of multi-header joining rules, the end of a
+ * header value is a token separator. This method does
+ * therefore not need to iterate over headers.
+ *
+ * @param pos the position in the current header at which to
+ * start the search
+ *
+ * @return the position of a token separator in the current header,
+ * or at the end
+ *
+ * @throws ParseException
+ * if a new token is found before a token separator.
+ * RFC 2616, section 2.1 explicitly requires a comma between
+ * tokens for <tt>#</tt>.
+ */
+ protected int findTokenSeparator(final int pos) {
+ int from = Args.notNegative(pos, "Search position");
+ boolean found = false;
+ final int to = this.currentHeader.length();
+ while (!found && (from < to)) {
+ final char ch = this.currentHeader.charAt(from);
+ if (isTokenSeparator(ch)) {
+ found = true;
+ } else if (isWhitespace(ch)) {
+ from++;
+ } else if (isTokenChar(ch)) {
+ throw new ParseException
+ ("Tokens without separator (pos " + from +
+ "): " + this.currentHeader);
+ } else {
+ throw new ParseException
+ ("Invalid character after token (pos " + from +
+ "): " + this.currentHeader);
+ }
+ }
+
+ return from;
+ }
+
+
+ /**
+ * Determines the ending position of the current token.
+ * This method will not leave the current header value,
+ * since the end of the header value is a token boundary.
+ *
+ * @param from the position of the first character of the token
+ *
+ * @return the position after the last character of the token.
+ * The behavior is undefined if <code>from</code> does not
+ * point to a token character in the current header value.
+ */
+ protected int findTokenEnd(final int from) {
+ Args.notNegative(from, "Search position");
+ final int to = this.currentHeader.length();
+ int end = from+1;
+ while ((end < to) && isTokenChar(this.currentHeader.charAt(end))) {
+ end++;
+ }
+
+ return end;
+ }
+
+
+ /**
+ * Checks whether a character is a token separator.
+ * RFC 2616, section 2.1 defines comma as the separator for
+ * <tt>#token</tt> sequences. The end of a header value will
+ * also separate tokens, but that is not a character check.
+ *
+ * @param ch the character to check
+ *
+ * @return <code>true</code> if the character is a token separator,
+ * <code>false</code> otherwise
+ */
+ protected boolean isTokenSeparator(final char ch) {
+ return (ch == ',');
+ }
+
+
+ /**
+ * Checks whether a character is a whitespace character.
+ * RFC 2616, section 2.2 defines space and horizontal tab as whitespace.
+ * The optional preceeding line break is irrelevant, since header
+ * continuation is handled transparently when parsing messages.
+ *
+ * @param ch the character to check
+ *
+ * @return <code>true</code> if the character is whitespace,
+ * <code>false</code> otherwise
+ */
+ protected boolean isWhitespace(final char ch) {
+
+ // we do not use Character.isWhitspace(ch) here, since that allows
+ // many control characters which are not whitespace as per RFC 2616
+ return ((ch == '\t') || Character.isSpaceChar(ch));
+ }
+
+
+ /**
+ * Checks whether a character is a valid token character.
+ * Whitespace, control characters, and HTTP separators are not
+ * valid token characters. The HTTP specification (RFC 2616, section 2.2)
+ * defines tokens only for the US-ASCII character set, this
+ * method extends the definition to other character sets.
+ *
+ * @param ch the character to check
+ *
+ * @return <code>true</code> if the character is a valid token start,
+ * <code>false</code> otherwise
+ */
+ protected boolean isTokenChar(final char ch) {
+
+ // common sense extension of ALPHA + DIGIT
+ if (Character.isLetterOrDigit(ch)) {
+ return true;
+ }
+
+ // common sense extension of CTL
+ if (Character.isISOControl(ch)) {
+ return false;
+ }
+
+ // no common sense extension for this
+ if (isHttpSeparator(ch)) {
+ return false;
+ }
+
+ // RFC 2616, section 2.2 defines a token character as
+ // "any CHAR except CTLs or separators". The controls
+ // and separators are included in the checks above.
+ // This will yield unexpected results for Unicode format characters.
+ // If that is a problem, overwrite isHttpSeparator(char) to filter
+ // out the false positives.
+ return true;
+ }
+
+
+ /**
+ * Checks whether a character is an HTTP separator.
+ * The implementation in this class checks only for the HTTP separators
+ * defined in RFC 2616, section 2.2. If you need to detect other
+ * separators beyond the US-ASCII character set, override this method.
+ *
+ * @param ch the character to check
+ *
+ * @return <code>true</code> if the character is an HTTP separator
+ */
+ protected boolean isHttpSeparator(final char ch) {
+ return (HTTP_SEPARATORS.indexOf(ch) >= 0);
+ }
+
+
+} // class BasicTokenIterator
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BufferedHeader.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BufferedHeader.java
new file mode 100644
index 000000000..11b70bdcb
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/BufferedHeader.java
@@ -0,0 +1,130 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.FormattedHeader;
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * This class represents a raw HTTP header whose content is parsed 'on demand'
+ * only when the header value needs to be consumed.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class BufferedHeader implements FormattedHeader, Cloneable, Serializable {
+
+ private static final long serialVersionUID = -2768352615787625448L;
+
+ /**
+ * Header name.
+ */
+ private final String name;
+
+ /**
+ * The buffer containing the entire header line.
+ */
+ private final CharArrayBuffer buffer;
+
+ /**
+ * The beginning of the header value in the buffer
+ */
+ private final int valuePos;
+
+
+ /**
+ * Creates a new header from a buffer.
+ * The name of the header will be parsed immediately,
+ * the value only if it is accessed.
+ *
+ * @param buffer the buffer containing the header to represent
+ *
+ * @throws ParseException in case of a parse error
+ */
+ public BufferedHeader(final CharArrayBuffer buffer)
+ throws ParseException {
+
+ super();
+ Args.notNull(buffer, "Char array buffer");
+ final int colon = buffer.indexOf(':');
+ if (colon == -1) {
+ throw new ParseException
+ ("Invalid header: " + buffer.toString());
+ }
+ final String s = buffer.substringTrimmed(0, colon);
+ if (s.length() == 0) {
+ throw new ParseException
+ ("Invalid header: " + buffer.toString());
+ }
+ this.buffer = buffer;
+ this.name = s;
+ this.valuePos = colon + 1;
+ }
+
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getValue() {
+ return this.buffer.substringTrimmed(this.valuePos, this.buffer.length());
+ }
+
+ public HeaderElement[] getElements() throws ParseException {
+ final ParserCursor cursor = new ParserCursor(0, this.buffer.length());
+ cursor.updatePos(this.valuePos);
+ return BasicHeaderValueParser.INSTANCE.parseElements(this.buffer, cursor);
+ }
+
+ public int getValuePos() {
+ return this.valuePos;
+ }
+
+ public CharArrayBuffer getBuffer() {
+ return this.buffer;
+ }
+
+ @Override
+ public String toString() {
+ return this.buffer.toString();
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ // buffer is considered immutable
+ // no need to make a copy of it
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderGroup.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderGroup.java
new file mode 100644
index 000000000..fe8cdce95
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderGroup.java
@@ -0,0 +1,311 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HeaderIterator;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * A class for combining a set of headers.
+ * This class allows for multiple headers with the same name and
+ * keeps track of the order in which headers were added.
+ *
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class HeaderGroup implements Cloneable, Serializable {
+
+ private static final long serialVersionUID = 2608834160639271617L;
+
+ /** The list of headers for this group, in the order in which they were added */
+ private final List<Header> headers;
+
+ /**
+ * Constructor for HeaderGroup.
+ */
+ public HeaderGroup() {
+ this.headers = new ArrayList<Header>(16);
+ }
+
+ /**
+ * Removes any contained headers.
+ */
+ public void clear() {
+ headers.clear();
+ }
+
+ /**
+ * Adds the given header to the group. The order in which this header was
+ * added is preserved.
+ *
+ * @param header the header to add
+ */
+ public void addHeader(final Header header) {
+ if (header == null) {
+ return;
+ }
+ headers.add(header);
+ }
+
+ /**
+ * Removes the given header.
+ *
+ * @param header the header to remove
+ */
+ public void removeHeader(final Header header) {
+ if (header == null) {
+ return;
+ }
+ headers.remove(header);
+ }
+
+ /**
+ * Replaces the first occurence of the header with the same name. If no header with
+ * the same name is found the given header is added to the end of the list.
+ *
+ * @param header the new header that should replace the first header with the same
+ * name if present in the list.
+ */
+ public void updateHeader(final Header header) {
+ if (header == null) {
+ return;
+ }
+ // HTTPCORE-361 : we don't use the for-each syntax, i.e.
+ // for (Header header : headers)
+ // as that creates an Iterator that needs to be garbage-collected
+ for (int i = 0; i < this.headers.size(); i++) {
+ final Header current = this.headers.get(i);
+ if (current.getName().equalsIgnoreCase(header.getName())) {
+ this.headers.set(i, header);
+ return;
+ }
+ }
+ this.headers.add(header);
+ }
+
+ /**
+ * Sets all of the headers contained within this group overriding any
+ * existing headers. The headers are added in the order in which they appear
+ * in the array.
+ *
+ * @param headers the headers to set
+ */
+ public void setHeaders(final Header[] headers) {
+ clear();
+ if (headers == null) {
+ return;
+ }
+ Collections.addAll(this.headers, headers);
+ }
+
+ /**
+ * Gets a header representing all of the header values with the given name.
+ * If more that one header with the given name exists the values will be
+ * combined with a "," as per RFC 2616.
+ *
+ * <p>Header name comparison is case insensitive.
+ *
+ * @param name the name of the header(s) to get
+ * @return a header with a condensed value or <code>null</code> if no
+ * headers by the given name are present
+ */
+ public Header getCondensedHeader(final String name) {
+ final Header[] hdrs = getHeaders(name);
+
+ if (hdrs.length == 0) {
+ return null;
+ } else if (hdrs.length == 1) {
+ return hdrs[0];
+ } else {
+ final CharArrayBuffer valueBuffer = new CharArrayBuffer(128);
+ valueBuffer.append(hdrs[0].getValue());
+ for (int i = 1; i < hdrs.length; i++) {
+ valueBuffer.append(", ");
+ valueBuffer.append(hdrs[i].getValue());
+ }
+
+ return new BasicHeader(name.toLowerCase(Locale.ENGLISH), valueBuffer.toString());
+ }
+ }
+
+ /**
+ * Gets all of the headers with the given name. The returned array
+ * maintains the relative order in which the headers were added.
+ *
+ * <p>Header name comparison is case insensitive.
+ *
+ * @param name the name of the header(s) to get
+ *
+ * @return an array of length >= 0
+ */
+ public Header[] getHeaders(final String name) {
+ final List<Header> headersFound = new ArrayList<Header>();
+ // HTTPCORE-361 : we don't use the for-each syntax, i.e.
+ // for (Header header : headers)
+ // as that creates an Iterator that needs to be garbage-collected
+ for (int i = 0; i < this.headers.size(); i++) {
+ final Header header = this.headers.get(i);
+ if (header.getName().equalsIgnoreCase(name)) {
+ headersFound.add(header);
+ }
+ }
+
+ return headersFound.toArray(new Header[headersFound.size()]);
+ }
+
+ /**
+ * Gets the first header with the given name.
+ *
+ * <p>Header name comparison is case insensitive.
+ *
+ * @param name the name of the header to get
+ * @return the first header or <code>null</code>
+ */
+ public Header getFirstHeader(final String name) {
+ // HTTPCORE-361 : we don't use the for-each syntax, i.e.
+ // for (Header header : headers)
+ // as that creates an Iterator that needs to be garbage-collected
+ for (int i = 0; i < this.headers.size(); i++) {
+ final Header header = this.headers.get(i);
+ if (header.getName().equalsIgnoreCase(name)) {
+ return header;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the last header with the given name.
+ *
+ * <p>Header name comparison is case insensitive.
+ *
+ * @param name the name of the header to get
+ * @return the last header or <code>null</code>
+ */
+ public Header getLastHeader(final String name) {
+ // start at the end of the list and work backwards
+ for (int i = headers.size() - 1; i >= 0; i--) {
+ final Header header = headers.get(i);
+ if (header.getName().equalsIgnoreCase(name)) {
+ return header;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets all of the headers contained within this group.
+ *
+ * @return an array of length >= 0
+ */
+ public Header[] getAllHeaders() {
+ return headers.toArray(new Header[headers.size()]);
+ }
+
+ /**
+ * Tests if headers with the given name are contained within this group.
+ *
+ * <p>Header name comparison is case insensitive.
+ *
+ * @param name the header name to test for
+ * @return <code>true</code> if at least one header with the name is
+ * contained, <code>false</code> otherwise
+ */
+ public boolean containsHeader(final String name) {
+ // HTTPCORE-361 : we don't use the for-each syntax, i.e.
+ // for (Header header : headers)
+ // as that creates an Iterator that needs to be garbage-collected
+ for (int i = 0; i < this.headers.size(); i++) {
+ final Header header = this.headers.get(i);
+ if (header.getName().equalsIgnoreCase(name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns an iterator over this group of headers.
+ *
+ * @return iterator over this group of headers.
+ *
+ * @since 4.0
+ */
+ public HeaderIterator iterator() {
+ return new BasicListHeaderIterator(this.headers, null);
+ }
+
+ /**
+ * Returns an iterator over the headers with a given name in this group.
+ *
+ * @param name the name of the headers over which to iterate, or
+ * <code>null</code> for all headers
+ *
+ * @return iterator over some headers in this group.
+ *
+ * @since 4.0
+ */
+ public HeaderIterator iterator(final String name) {
+ return new BasicListHeaderIterator(this.headers, name);
+ }
+
+ /**
+ * Returns a copy of this object
+ *
+ * @return copy of this object
+ *
+ * @since 4.0
+ */
+ public HeaderGroup copy() {
+ final HeaderGroup clone = new HeaderGroup();
+ clone.headers.addAll(this.headers);
+ return clone;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ @Override
+ public String toString() {
+ return this.headers.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueFormatter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueFormatter.java
new file mode 100644
index 000000000..8a1acc04e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueFormatter.java
@@ -0,0 +1,122 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Interface for formatting elements of a header value.
+ * This is the complement to {@link HeaderValueParser}.
+ * Instances of this interface are expected to be stateless and thread-safe.
+ *
+ * <p>
+ * All formatting methods accept an optional buffer argument.
+ * If a buffer is passed in, the formatted element will be appended
+ * and the modified buffer is returned. If no buffer is passed in,
+ * a new buffer will be created and filled with the formatted element.
+ * In both cases, the caller is allowed to modify the returned buffer.
+ * </p>
+ *
+ * @since 4.0
+ */
+public interface HeaderValueFormatter {
+
+ /**
+ * Formats an array of header elements.
+ *
+ * @param buffer the buffer to append to, or
+ * <code>null</code> to create a new buffer
+ * @param elems the header elements to format
+ * @param quote <code>true</code> to always format with quoted values,
+ * <code>false</code> to use quotes only when necessary
+ *
+ * @return a buffer with the formatted header elements.
+ * If the <code>buffer</code> argument was not <code>null</code>,
+ * that buffer will be used and returned.
+ */
+ CharArrayBuffer formatElements(CharArrayBuffer buffer,
+ HeaderElement[] elems,
+ boolean quote);
+
+ /**
+ * Formats one header element.
+ *
+ * @param buffer the buffer to append to, or
+ * <code>null</code> to create a new buffer
+ * @param elem the header element to format
+ * @param quote <code>true</code> to always format with quoted values,
+ * <code>false</code> to use quotes only when necessary
+ *
+ * @return a buffer with the formatted header element.
+ * If the <code>buffer</code> argument was not <code>null</code>,
+ * that buffer will be used and returned.
+ */
+ CharArrayBuffer formatHeaderElement(CharArrayBuffer buffer,
+ HeaderElement elem,
+ boolean quote);
+
+ /**
+ * Formats the parameters of a header element.
+ * That's a list of name-value pairs, to be separated by semicolons.
+ * This method will <i>not</i> generate a leading semicolon.
+ *
+ * @param buffer the buffer to append to, or
+ * <code>null</code> to create a new buffer
+ * @param nvps the parameters (name-value pairs) to format
+ * @param quote <code>true</code> to always format with quoted values,
+ * <code>false</code> to use quotes only when necessary
+ *
+ * @return a buffer with the formatted parameters.
+ * If the <code>buffer</code> argument was not <code>null</code>,
+ * that buffer will be used and returned.
+ */
+ CharArrayBuffer formatParameters(CharArrayBuffer buffer,
+ NameValuePair[] nvps,
+ boolean quote);
+
+ /**
+ * Formats one name-value pair, where the value is optional.
+ *
+ * @param buffer the buffer to append to, or
+ * <code>null</code> to create a new buffer
+ * @param nvp the name-value pair to format
+ * @param quote <code>true</code> to always format with a quoted value,
+ * <code>false</code> to use quotes only when necessary
+ *
+ * @return a buffer with the formatted name-value pair.
+ * If the <code>buffer</code> argument was not <code>null</code>,
+ * that buffer will be used and returned.
+ */
+ CharArrayBuffer formatNameValuePair(CharArrayBuffer buffer,
+ NameValuePair nvp,
+ boolean quote);
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueParser.java
new file mode 100644
index 000000000..5286249c7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/HeaderValueParser.java
@@ -0,0 +1,134 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Interface for parsing header values into elements.
+ * Instances of this interface are expected to be stateless and thread-safe.
+ *
+ * @since 4.0
+ */
+public interface HeaderValueParser {
+
+ /**
+ * Parses a header value into elements.
+ * Parse errors are indicated as <code>RuntimeException</code>.
+ * <p>
+ * Some HTTP headers (such as the set-cookie header) have values that
+ * can be decomposed into multiple elements. In order to be processed
+ * by this parser, such headers must be in the following form:
+ * </p>
+ * <pre>
+ * header = [ element ] *( "," [ element ] )
+ * element = name [ "=" [ value ] ] *( ";" [ param ] )
+ * param = name [ "=" [ value ] ]
+ *
+ * name = token
+ * value = ( token | quoted-string )
+ *
+ * token = 1*&lt;any char except "=", ",", ";", &lt;"&gt; and
+ * white space&gt;
+ * quoted-string = &lt;"&gt; *( text | quoted-char ) &lt;"&gt;
+ * text = any char except &lt;"&gt;
+ * quoted-char = "\" char
+ * </pre>
+ * <p>
+ * Any amount of white space is allowed between any part of the
+ * header, element or param and is ignored. A missing value in any
+ * element or param will be stored as the empty {@link String};
+ * if the "=" is also missing <var>null</var> will be stored instead.
+ * </p>
+ *
+ * @param buffer buffer holding the header value to parse
+ * @param cursor the parser cursor containing the current position and
+ * the bounds within the buffer for the parsing operation
+ *
+ * @return an array holding all elements of the header value
+ *
+ * @throws ParseException in case of a parse error
+ */
+ HeaderElement[] parseElements(
+ CharArrayBuffer buffer,
+ ParserCursor cursor) throws ParseException;
+
+ /**
+ * Parses a single header element.
+ * A header element consist of a semicolon-separate list
+ * of name=value definitions.
+ *
+ * @param buffer buffer holding the element to parse
+ * @param cursor the parser cursor containing the current position and
+ * the bounds within the buffer for the parsing operation
+ *
+ * @return the parsed element
+ *
+ * @throws ParseException in case of a parse error
+ */
+ HeaderElement parseHeaderElement(
+ CharArrayBuffer buffer,
+ ParserCursor cursor) throws ParseException;
+
+ /**
+ * Parses a list of name-value pairs.
+ * These lists are used to specify parameters to a header element.
+ * Parse errors are indicated as <code>ParseException</code>.
+ *
+ * @param buffer buffer holding the name-value list to parse
+ * @param cursor the parser cursor containing the current position and
+ * the bounds within the buffer for the parsing operation
+ *
+ * @return an array holding all items of the name-value list
+ *
+ * @throws ParseException in case of a parse error
+ */
+ NameValuePair[] parseParameters(
+ CharArrayBuffer buffer,
+ ParserCursor cursor) throws ParseException;
+
+
+ /**
+ * Parses a name=value specification, where the = and value are optional.
+ *
+ * @param buffer the buffer holding the name-value pair to parse
+ * @param cursor the parser cursor containing the current position and
+ * the bounds within the buffer for the parsing operation
+ *
+ * @return the name-value pair, where the value is <code>null</code>
+ * if no value is specified
+ */
+ NameValuePair parseNameValuePair(
+ CharArrayBuffer buffer,
+ ParserCursor cursor) throws ParseException;
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineFormatter.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineFormatter.java
new file mode 100644
index 000000000..33e751a75
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineFormatter.java
@@ -0,0 +1,131 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Interface for formatting elements of the HEAD section of an HTTP message.
+ * This is the complement to {@link LineParser}.
+ * There are individual methods for formatting a request line, a
+ * status line, or a header line. The formatting does <i>not</i> include the
+ * trailing line break sequence CR-LF.
+ * Instances of this interface are expected to be stateless and thread-safe.
+ *
+ * <p>
+ * The formatted lines are returned in memory, the formatter does not depend
+ * on any specific IO mechanism.
+ * In order to avoid unnecessary creation of temporary objects,
+ * a buffer can be passed as argument to all formatting methods.
+ * The implementation may or may not actually use that buffer for formatting.
+ * If it is used, the buffer will first be cleared by the
+ * <code>formatXXX</code> methods.
+ * The argument buffer can always be re-used after the call. The buffer
+ * returned as the result, if it is different from the argument buffer,
+ * MUST NOT be modified.
+ * </p>
+ *
+ * @since 4.0
+ */
+public interface LineFormatter {
+
+ /**
+ * Formats a protocol version.
+ * This method does <i>not</i> follow the general contract for
+ * <code>buffer</code> arguments.
+ * It does <i>not</i> clear the argument buffer, but appends instead.
+ * The returned buffer can always be modified by the caller.
+ * Because of these differing conventions, it is not named
+ * <code>formatProtocolVersion</code>.
+ *
+ * @param buffer a buffer to which to append, or <code>null</code>
+ * @param version the protocol version to format
+ *
+ * @return a buffer with the formatted protocol version appended.
+ * The caller is allowed to modify the result buffer.
+ * If the <code>buffer</code> argument is not <code>null</code>,
+ * the returned buffer is the argument buffer.
+ */
+ CharArrayBuffer appendProtocolVersion(CharArrayBuffer buffer,
+ ProtocolVersion version);
+
+ /**
+ * Formats a request line.
+ *
+ * @param buffer a buffer available for formatting, or
+ * <code>null</code>.
+ * The buffer will be cleared before use.
+ * @param reqline the request line to format
+ *
+ * @return the formatted request line
+ */
+ CharArrayBuffer formatRequestLine(CharArrayBuffer buffer,
+ RequestLine reqline);
+
+ /**
+ * Formats a status line.
+ *
+ * @param buffer a buffer available for formatting, or
+ * <code>null</code>.
+ * The buffer will be cleared before use.
+ * @param statline the status line to format
+ *
+ * @return the formatted status line
+ *
+ * @throws ch.boye.httpclientandroidlib.ParseException in case of a parse error
+ */
+ CharArrayBuffer formatStatusLine(CharArrayBuffer buffer,
+ StatusLine statline);
+
+ /**
+ * Formats a header.
+ * Due to header continuation, the result may be multiple lines.
+ * In order to generate well-formed HTTP, the lines in the result
+ * must be separated by the HTTP line break sequence CR-LF.
+ * There is <i>no</i> trailing CR-LF in the result.
+ * <br/>
+ * See the class comment for details about the buffer argument.
+ *
+ * @param buffer a buffer available for formatting, or
+ * <code>null</code>.
+ * The buffer will be cleared before use.
+ * @param header the header to format
+ *
+ * @return a buffer holding the formatted header, never <code>null</code>.
+ * The returned buffer may be different from the argument buffer.
+ *
+ * @throws ch.boye.httpclientandroidlib.ParseException in case of a parse error
+ */
+ CharArrayBuffer formatHeader(CharArrayBuffer buffer,
+ Header header);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineParser.java
new file mode 100644
index 000000000..d94ca3d75
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/LineParser.java
@@ -0,0 +1,137 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.RequestLine;
+import ch.boye.httpclientandroidlib.StatusLine;
+import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
+
+/**
+ * Interface for parsing lines in the HEAD section of an HTTP message.
+ * There are individual methods for parsing a request line, a
+ * status line, or a header line.
+ * The lines to parse are passed in memory, the parser does not depend
+ * on any specific IO mechanism.
+ * Instances of this interface are expected to be stateless and thread-safe.
+ *
+ * @since 4.0
+ */
+public interface LineParser {
+
+ /**
+ * Parses the textual representation of a protocol version.
+ * This is needed for parsing request lines (last element)
+ * as well as status lines (first element).
+ *
+ * @param buffer a buffer holding the protocol version to parse
+ * @param cursor the parser cursor containing the current position and
+ * the bounds within the buffer for the parsing operation
+ *
+ * @return the parsed protocol version
+ *
+ * @throws ParseException in case of a parse error
+ */
+ ProtocolVersion parseProtocolVersion(
+ CharArrayBuffer buffer,
+ ParserCursor cursor) throws ParseException;
+
+ /**
+ * Checks whether there likely is a protocol version in a line.
+ * This method implements a <i>heuristic</i> to check for a
+ * likely protocol version specification. It does <i>not</i>
+ * guarantee that {@link #parseProtocolVersion} would not
+ * detect a parse error.
+ * This can be used to detect garbage lines before a request
+ * or status line.
+ *
+ * @param buffer a buffer holding the line to inspect
+ * @param cursor the cursor at which to check for a protocol version, or
+ * negative for "end of line". Whether the check tolerates
+ * whitespace before or after the protocol version is
+ * implementation dependent.
+ *
+ * @return <code>true</code> if there is a protocol version at the
+ * argument index (possibly ignoring whitespace),
+ * <code>false</code> otherwise
+ */
+ boolean hasProtocolVersion(
+ CharArrayBuffer buffer,
+ ParserCursor cursor);
+
+ /**
+ * Parses a request line.
+ *
+ * @param buffer a buffer holding the line to parse
+ * @param cursor the parser cursor containing the current position and
+ * the bounds within the buffer for the parsing operation
+ *
+ * @return the parsed request line
+ *
+ * @throws ParseException in case of a parse error
+ */
+ RequestLine parseRequestLine(
+ CharArrayBuffer buffer,
+ ParserCursor cursor) throws ParseException;
+
+ /**
+ * Parses a status line.
+ *
+ * @param buffer a buffer holding the line to parse
+ * @param cursor the parser cursor containing the current position and
+ * the bounds within the buffer for the parsing operation
+ *
+ * @return the parsed status line
+ *
+ * @throws ParseException in case of a parse error
+ */
+ StatusLine parseStatusLine(
+ CharArrayBuffer buffer,
+ ParserCursor cursor) throws ParseException;
+
+ /**
+ * Creates a header from a line.
+ * The full header line is expected here. Header continuation lines
+ * must be joined by the caller before invoking this method.
+ *
+ * @param buffer a buffer holding the full header line.
+ * This buffer MUST NOT be re-used afterwards, since
+ * the returned object may reference the contents later.
+ *
+ * @return the header in the argument buffer.
+ * The returned object MAY be a wrapper for the argument buffer.
+ * The argument buffer MUST NOT be re-used or changed afterwards.
+ *
+ * @throws ParseException in case of a parse error
+ */
+ Header parseHeader(CharArrayBuffer buffer)
+ throws ParseException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/ParserCursor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/ParserCursor.java
new file mode 100644
index 000000000..163352bb7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/ParserCursor.java
@@ -0,0 +1,100 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.message;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * This class represents a context of a parsing operation:
+ * <ul>
+ * <li>the current position the parsing operation is expected to start at</li>
+ * <li>the bounds limiting the scope of the parsing operation</li>
+ * </ul>
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public class ParserCursor {
+
+ private final int lowerBound;
+ private final int upperBound;
+ private int pos;
+
+ public ParserCursor(final int lowerBound, final int upperBound) {
+ super();
+ if (lowerBound < 0) {
+ throw new IndexOutOfBoundsException("Lower bound cannot be negative");
+ }
+ if (lowerBound > upperBound) {
+ throw new IndexOutOfBoundsException("Lower bound cannot be greater then upper bound");
+ }
+ this.lowerBound = lowerBound;
+ this.upperBound = upperBound;
+ this.pos = lowerBound;
+ }
+
+ public int getLowerBound() {
+ return this.lowerBound;
+ }
+
+ public int getUpperBound() {
+ return this.upperBound;
+ }
+
+ public int getPos() {
+ return this.pos;
+ }
+
+ public void updatePos(final int pos) {
+ if (pos < this.lowerBound) {
+ throw new IndexOutOfBoundsException("pos: "+pos+" < lowerBound: "+this.lowerBound);
+ }
+ if (pos > this.upperBound) {
+ throw new IndexOutOfBoundsException("pos: "+pos+" > upperBound: "+this.upperBound);
+ }
+ this.pos = pos;
+ }
+
+ public boolean atEnd() {
+ return this.pos >= this.upperBound;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append('[');
+ buffer.append(Integer.toString(this.lowerBound));
+ buffer.append('>');
+ buffer.append(Integer.toString(this.pos));
+ buffer.append('>');
+ buffer.append(Integer.toString(this.upperBound));
+ buffer.append(']');
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/package-info.java
new file mode 100644
index 000000000..bac6c2e32
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/message/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Core HTTP message components, message element parser
+ * and writer APIs and their default implementations.
+ */
+package ch.boye.httpclientandroidlib.message;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/package-info.java
new file mode 100644
index 000000000..3001825af
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Core HTTP component APIs and primitives.
+ * <p/>
+ * These deal with the fundamental things required for using the
+ * HTTP protocol, such as representing a
+ * {@link ch.boye.httpclientandroidlib.HttpMessage message} including it's
+ * {@link ch.boye.httpclientandroidlib.Header headers} and optional
+ * {@link ch.boye.httpclientandroidlib.HttpEntity entity}, and
+ * {@link ch.boye.httpclientandroidlib.HttpConnection connections}
+ * over which messages are sent. In order to prepare messages
+ * before sending or after receiving, there are interceptors for
+ * {@link ch.boye.httpclientandroidlib.HttpRequestInterceptor requests} and
+ * {@link ch.boye.httpclientandroidlib.HttpResponseInterceptor responses}.
+ */
+package ch.boye.httpclientandroidlib;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/AbstractHttpParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/AbstractHttpParams.java
new file mode 100644
index 000000000..0d41b8f00
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/AbstractHttpParams.java
@@ -0,0 +1,124 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import java.util.Set;
+
+/**
+ * Abstract base class for parameter collections.
+ * Type specific setters and getters are mapped to the abstract,
+ * generic getters and setters.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public abstract class AbstractHttpParams implements HttpParams, HttpParamsNames {
+
+ /**
+ * Instantiates parameters.
+ */
+ protected AbstractHttpParams() {
+ super();
+ }
+
+ public long getLongParameter(final String name, final long defaultValue) {
+ final Object param = getParameter(name);
+ if (param == null) {
+ return defaultValue;
+ }
+ return ((Long) param).longValue();
+ }
+
+ public HttpParams setLongParameter(final String name, final long value) {
+ setParameter(name, Long.valueOf(value));
+ return this;
+ }
+
+ public int getIntParameter(final String name, final int defaultValue) {
+ final Object param = getParameter(name);
+ if (param == null) {
+ return defaultValue;
+ }
+ return ((Integer) param).intValue();
+ }
+
+ public HttpParams setIntParameter(final String name, final int value) {
+ setParameter(name, Integer.valueOf(value));
+ return this;
+ }
+
+ public double getDoubleParameter(final String name, final double defaultValue) {
+ final Object param = getParameter(name);
+ if (param == null) {
+ return defaultValue;
+ }
+ return ((Double) param).doubleValue();
+ }
+
+ public HttpParams setDoubleParameter(final String name, final double value) {
+ setParameter(name, Double.valueOf(value));
+ return this;
+ }
+
+ public boolean getBooleanParameter(final String name, final boolean defaultValue) {
+ final Object param = getParameter(name);
+ if (param == null) {
+ return defaultValue;
+ }
+ return ((Boolean) param).booleanValue();
+ }
+
+ public HttpParams setBooleanParameter(final String name, final boolean value) {
+ setParameter(name, value ? Boolean.TRUE : Boolean.FALSE);
+ return this;
+ }
+
+ public boolean isParameterTrue(final String name) {
+ return getBooleanParameter(name, false);
+ }
+
+ public boolean isParameterFalse(final String name) {
+ return !getBooleanParameter(name, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Dummy implementation - must be overridden by subclasses.
+ *
+ * @since 4.2
+ * @throws UnsupportedOperationException - always
+ */
+ public Set<String> getNames(){
+ throw new UnsupportedOperationException();
+ }
+
+} // class AbstractHttpParams
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/BasicHttpParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/BasicHttpParams.java
new file mode 100644
index 000000000..420ac1a08
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/BasicHttpParams.java
@@ -0,0 +1,190 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+/**
+ * Default implementation of {@link HttpParams} interface.
+ * <p>
+ * Please note access to the internal structures of this class is not
+ * synchronized and therefore this class may be thread-unsafe.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+@ThreadSafe
+public class BasicHttpParams extends AbstractHttpParams implements Serializable, Cloneable {
+
+ private static final long serialVersionUID = -7086398485908701455L;
+
+ /** Map of HTTP parameters that this collection contains. */
+ private final Map<String, Object> parameters = new ConcurrentHashMap<String, Object>();
+
+ public BasicHttpParams() {
+ super();
+ }
+
+ public Object getParameter(final String name) {
+ return this.parameters.get(name);
+ }
+
+ public HttpParams setParameter(final String name, final Object value) {
+ if (name == null) {
+ return this;
+ }
+ if (value != null) {
+ this.parameters.put(name, value);
+ } else {
+ this.parameters.remove(name);
+ }
+ return this;
+ }
+
+ public boolean removeParameter(final String name) {
+ //this is to avoid the case in which the key has a null value
+ if (this.parameters.containsKey(name)) {
+ this.parameters.remove(name);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Assigns the value to all the parameter with the given names
+ *
+ * @param names array of parameter names
+ * @param value parameter value
+ */
+ public void setParameters(final String[] names, final Object value) {
+ for (final String name : names) {
+ setParameter(name, value);
+ }
+ }
+
+ /**
+ * Is the parameter set?
+ * <p>
+ * Uses {@link #getParameter(String)} (which is overrideable) to
+ * fetch the parameter value, if any.
+ * <p>
+ * Also @see {@link #isParameterSetLocally(String)}
+ *
+ * @param name parameter name
+ * @return true if parameter is defined and non-null
+ */
+ public boolean isParameterSet(final String name) {
+ return getParameter(name) != null;
+ }
+
+ /**
+ * Is the parameter set in this object?
+ * <p>
+ * The parameter value is fetched directly.
+ * <p>
+ * Also @see {@link #isParameterSet(String)}
+ *
+ * @param name parameter name
+ * @return true if parameter is defined and non-null
+ */
+ public boolean isParameterSetLocally(final String name) {
+ return this.parameters.get(name) != null;
+ }
+
+ /**
+ * Removes all parameters from this collection.
+ */
+ public void clear() {
+ this.parameters.clear();
+ }
+
+ /**
+ * Creates a copy of these parameters.
+ * This implementation calls {@link #clone()}.
+ *
+ * @return a new set of params holding a copy of the
+ * <i>local</i> parameters in this object.
+ *
+ * @throws UnsupportedOperationException if the clone() fails
+ */
+ public HttpParams copy() {
+ try {
+ return (HttpParams) clone();
+ } catch (final CloneNotSupportedException ex) {
+ throw new UnsupportedOperationException("Cloning not supported");
+ }
+ }
+
+ /**
+ * Clones the instance.
+ * Uses {@link #copyParams(HttpParams)} to copy the parameters.
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ final BasicHttpParams clone = (BasicHttpParams) super.clone();
+ copyParams(clone);
+ return clone;
+ }
+
+ /**
+ * Copies the locally defined parameters to the argument parameters.
+ * This method is called from {@link #clone()}.
+ *
+ * @param target the parameters to which to copy
+ * @since 4.2
+ */
+ public void copyParams(final HttpParams target) {
+ for (final Map.Entry<String, Object> me : this.parameters.entrySet()) {
+ target.setParameter(me.getKey(), me.getValue());
+ }
+ }
+
+ /**
+ * Returns the current set of names.
+ *
+ * Changes to the underlying HttpParams are not reflected
+ * in the set - it is a snapshot.
+ *
+ * @return the names, as a Set<String>
+ * @since 4.2
+ */
+ @Override
+ public Set<String> getNames() {
+ return new HashSet<String>(this.parameters.keySet());
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreConnectionPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreConnectionPNames.java
new file mode 100644
index 000000000..dc9c63429
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreConnectionPNames.java
@@ -0,0 +1,170 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+/**
+ * Defines parameter names for connections in HttpCore.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public interface CoreConnectionPNames {
+
+ /**
+ * Defines the socket timeout (<code>SO_TIMEOUT</code>) in milliseconds,
+ * which is the timeout for waiting for data or, put differently,
+ * a maximum period inactivity between two consecutive data packets).
+ * A timeout value of zero is interpreted as an infinite timeout.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ * @see java.net.SocketOptions#SO_TIMEOUT
+ */
+ public static final String SO_TIMEOUT = "http.socket.timeout";
+
+ /**
+ * Determines whether Nagle's algorithm is to be used. The Nagle's algorithm
+ * tries to conserve bandwidth by minimizing the number of segments that are
+ * sent. When applications wish to decrease network latency and increase
+ * performance, they can disable Nagle's algorithm (that is enable
+ * TCP_NODELAY). Data will be sent earlier, at the cost of an increase
+ * in bandwidth consumption.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ * @see java.net.SocketOptions#TCP_NODELAY
+ */
+ public static final String TCP_NODELAY = "http.tcp.nodelay";
+
+ /**
+ * Determines the size of the internal socket buffer used to buffer data
+ * while receiving / transmitting HTTP messages.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String SOCKET_BUFFER_SIZE = "http.socket.buffer-size";
+
+ /**
+ * Sets SO_LINGER with the specified linger time in seconds. The maximum
+ * timeout value is platform specific. Value <code>0</code> implies that
+ * the option is disabled. Value <code>-1</code> implies that the JRE
+ * default is used. The setting only affects the socket close operation.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ * @see java.net.SocketOptions#SO_LINGER
+ */
+ public static final String SO_LINGER = "http.socket.linger";
+
+ /**
+ * Defines whether the socket can be bound even though a previous connection is
+ * still in a timeout state.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ * @see java.net.Socket#setReuseAddress(boolean)
+ *
+ * @since 4.1
+ */
+ public static final String SO_REUSEADDR = "http.socket.reuseaddr";
+
+ /**
+ * Determines the timeout in milliseconds until a connection is established.
+ * A timeout value of zero is interpreted as an infinite timeout.
+ * <p>
+ * Please note this parameter can only be applied to connections that
+ * are bound to a particular local address.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String CONNECTION_TIMEOUT = "http.connection.timeout";
+
+ /**
+ * Determines whether stale connection check is to be used. The stale
+ * connection check can cause up to 30 millisecond overhead per request and
+ * should be used only when appropriate. For performance critical
+ * operations this check should be disabled.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String STALE_CONNECTION_CHECK = "http.connection.stalecheck";
+
+ /**
+ * Determines the maximum line length limit. If set to a positive value,
+ * any HTTP line exceeding this limit will cause an IOException. A negative
+ * or zero value will effectively disable the check.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String MAX_LINE_LENGTH = "http.connection.max-line-length";
+
+ /**
+ * Determines the maximum HTTP header count allowed. If set to a positive
+ * value, the number of HTTP headers received from the data stream exceeding
+ * this limit will cause an IOException. A negative or zero value will
+ * effectively disable the check.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String MAX_HEADER_COUNT = "http.connection.max-header-count";
+
+ /**
+ * Defines the size limit below which data chunks should be buffered in a session I/O buffer
+ * in order to minimize native method invocations on the underlying network socket.
+ * The optimal value of this parameter can be platform specific and defines a trade-off
+ * between performance of memory copy operations and that of native method invocation.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ *
+ * @since 4.1
+ */
+ public static final String MIN_CHUNK_LIMIT = "http.connection.min-chunk-limit";
+
+
+ /**
+ * Defines whether or not TCP is to send automatically a keepalive probe to the peer
+ * after an interval of inactivity (no data exchanged in either direction) between this
+ * host and the peer. The purpose of this option is to detect if the peer host crashes.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ * @see java.net.SocketOptions#SO_KEEPALIVE
+ * @since 4.2
+ */
+ public static final String SO_KEEPALIVE = "http.socket.keepalive";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreProtocolPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreProtocolPNames.java
new file mode 100644
index 000000000..68cf63c8b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/CoreProtocolPNames.java
@@ -0,0 +1,152 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+/**
+ * Defines parameter names for protocol execution in HttpCore.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public interface CoreProtocolPNames {
+
+ /**
+ * Defines the {@link ch.boye.httpclientandroidlib.ProtocolVersion} used per default.
+ * <p>
+ * This parameter expects a value of type {@link ch.boye.httpclientandroidlib.ProtocolVersion}.
+ * </p>
+ */
+ public static final String PROTOCOL_VERSION = "http.protocol.version";
+
+ /**
+ * Defines the charset to be used for encoding HTTP protocol elements.
+ * <p>
+ * This parameter expects a value of type {@link String}.
+ * </p>
+ */
+ public static final String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset";
+
+ /**
+ * Defines the charset to be used per default for encoding content body.
+ * <p>
+ * This parameter expects a value of type {@link String}.
+ * </p>
+ */
+ public static final String HTTP_CONTENT_CHARSET = "http.protocol.content-charset";
+
+ /**
+ * Defines the content of the <code>User-Agent</code> header.
+ * <p>
+ * This parameter expects a value of type {@link String}.
+ * </p>
+ */
+ public static final String USER_AGENT = "http.useragent";
+
+ /**
+ * Defines the content of the <code>Server</code> header.
+ * <p>
+ * This parameter expects a value of type {@link String}.
+ * </p>
+ */
+ public static final String ORIGIN_SERVER = "http.origin-server";
+
+ /**
+ * Defines whether responses with an invalid <code>Transfer-Encoding</code>
+ * header should be rejected.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String STRICT_TRANSFER_ENCODING = "http.protocol.strict-transfer-encoding";
+
+ /**
+ * <p>
+ * Activates 'Expect: 100-Continue' handshake for the
+ * entity enclosing methods. The purpose of the 'Expect: 100-Continue'
+ * handshake is to allow a client that is sending a request message with
+ * a request body to determine if the origin server is willing to
+ * accept the request (based on the request headers) before the client
+ * sends the request body.
+ * </p>
+ *
+ * <p>
+ * The use of the 'Expect: 100-continue' handshake can result in
+ * a noticeable performance improvement for entity enclosing requests
+ * (such as POST and PUT) that require the target server's
+ * authentication.
+ * </p>
+ *
+ * <p>
+ * 'Expect: 100-continue' handshake should be used with
+ * caution, as it may cause problems with HTTP servers and
+ * proxies that do not support HTTP/1.1 protocol.
+ * </p>
+ *
+ * This parameter expects a value of type {@link Boolean}.
+ */
+ public static final String USE_EXPECT_CONTINUE = "http.protocol.expect-continue";
+
+ /**
+ * <p>
+ * Defines the maximum period of time in milliseconds the client should spend
+ * waiting for a 100-continue response.
+ * </p>
+ *
+ * This parameter expects a value of type {@link Integer}.
+ */
+ public static final String WAIT_FOR_CONTINUE = "http.protocol.wait-for-continue";
+
+ /**
+ * <p>
+ * Defines the action to perform upon receiving a malformed input. If the input byte sequence
+ * is not legal for this charset then the input is said to be malformed
+ * </p>
+ *
+ * This parameter expects a value of type {@link java.nio.charset.CodingErrorAction}
+ *
+ * @since 4.2
+ */
+ public static final String HTTP_MALFORMED_INPUT_ACTION = "http.malformed.input.action";
+
+ /**
+ * <p>
+ * Defines the action to perform upon receiving an unmappable input. If the input byte sequence
+ * is legal but cannot be mapped to a valid Unicode character then the input is said to be
+ * unmappable
+ * </p>
+ *
+ * This parameter expects a value of type {@link java.nio.charset.CodingErrorAction}
+ *
+ * @since 4.2
+ */
+ public static final String HTTP_UNMAPPABLE_INPUT_ACTION = "http.unmappable.input.action";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/DefaultedHttpParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/DefaultedHttpParams.java
new file mode 100644
index 000000000..88be440c3
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/DefaultedHttpParams.java
@@ -0,0 +1,163 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * {@link HttpParams} implementation that delegates resolution of a parameter
+ * to the given default {@link HttpParams} instance if the parameter is not
+ * present in the local one. The state of the local collection can be mutated,
+ * whereas the default collection is treated as read-only.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public final class DefaultedHttpParams extends AbstractHttpParams {
+
+ private final HttpParams local;
+ private final HttpParams defaults;
+
+ /**
+ * Create the defaulted set of HttpParams.
+ *
+ * @param local the mutable set of HttpParams
+ * @param defaults the default set of HttpParams, not mutated by this class
+ */
+ public DefaultedHttpParams(final HttpParams local, final HttpParams defaults) {
+ super();
+ this.local = Args.notNull(local, "Local HTTP parameters");
+ this.defaults = defaults;
+ }
+
+ /**
+ * Creates a copy of the local collection with the same default
+ */
+ public HttpParams copy() {
+ final HttpParams clone = this.local.copy();
+ return new DefaultedHttpParams(clone, this.defaults);
+ }
+
+ /**
+ * Retrieves the value of the parameter from the local collection and, if the
+ * parameter is not set locally, delegates its resolution to the default
+ * collection.
+ */
+ public Object getParameter(final String name) {
+ Object obj = this.local.getParameter(name);
+ if (obj == null && this.defaults != null) {
+ obj = this.defaults.getParameter(name);
+ }
+ return obj;
+ }
+
+ /**
+ * Attempts to remove the parameter from the local collection. This method
+ * <i>does not</i> modify the default collection.
+ */
+ public boolean removeParameter(final String name) {
+ return this.local.removeParameter(name);
+ }
+
+ /**
+ * Sets the parameter in the local collection. This method <i>does not</i>
+ * modify the default collection.
+ */
+ public HttpParams setParameter(final String name, final Object value) {
+ return this.local.setParameter(name, value);
+ }
+
+ /**
+ *
+ * @return the default HttpParams collection
+ */
+ public HttpParams getDefaults() {
+ return this.defaults;
+ }
+
+ /**
+ * Returns the current set of names
+ * from both the local and default HttpParams instances.
+ *
+ * Changes to the underlying HttpParams intances are not reflected
+ * in the set - it is a snapshot.
+ *
+ * @return the combined set of names, as a Set<String>
+ * @since 4.2
+ * @throws UnsupportedOperationException if either the local or default HttpParams instances do not implement HttpParamsNames
+ */
+ @Override
+ public Set<String> getNames() {
+ final Set<String> combined = new HashSet<String>(getNames(defaults));
+ combined.addAll(getNames(this.local));
+ return combined ;
+ }
+
+ /**
+ * Returns the current set of defaults names.
+ *
+ * Changes to the underlying HttpParams are not reflected
+ * in the set - it is a snapshot.
+ *
+ * @return the names, as a Set<String>
+ * @since 4.2
+ * @throws UnsupportedOperationException if the default HttpParams instance does not implement HttpParamsNames
+ */
+ public Set<String> getDefaultNames() {
+ return new HashSet<String>(getNames(this.defaults));
+ }
+
+ /**
+ * Returns the current set of local names.
+ *
+ * Changes to the underlying HttpParams are not reflected
+ * in the set - it is a snapshot.
+ *
+ * @return the names, as a Set<String>
+ * @since 4.2
+ * @throws UnsupportedOperationException if the local HttpParams instance does not implement HttpParamsNames
+ */
+ public Set<String> getLocalNames() {
+ return new HashSet<String>(getNames(this.local));
+ }
+
+ // Helper method
+ private Set<String> getNames(final HttpParams params) {
+ if (params instanceof HttpParamsNames) {
+ return ((HttpParamsNames) params).getNames();
+ }
+ throw new UnsupportedOperationException("HttpParams instance does not implement HttpParamsNames");
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpAbstractParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpAbstractParamBean.java
new file mode 100644
index 000000000..b3010f1ce
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpAbstractParamBean.java
@@ -0,0 +1,48 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public abstract class HttpAbstractParamBean {
+
+ protected final HttpParams params;
+
+ public HttpAbstractParamBean (final HttpParams params) {
+ super();
+ this.params = Args.notNull(params, "HTTP parameters");
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParamBean.java
new file mode 100644
index 000000000..d6e6cc471
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParamBean.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate HTTP connection parameters using Java Beans
+ * conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public class HttpConnectionParamBean extends HttpAbstractParamBean {
+
+ public HttpConnectionParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ public void setSoTimeout (final int soTimeout) {
+ HttpConnectionParams.setSoTimeout(params, soTimeout);
+ }
+
+ public void setTcpNoDelay (final boolean tcpNoDelay) {
+ HttpConnectionParams.setTcpNoDelay(params, tcpNoDelay);
+ }
+
+ public void setSocketBufferSize (final int socketBufferSize) {
+ HttpConnectionParams.setSocketBufferSize(params, socketBufferSize);
+ }
+
+ public void setLinger (final int linger) {
+ HttpConnectionParams.setLinger(params, linger);
+ }
+
+ public void setConnectionTimeout (final int connectionTimeout) {
+ HttpConnectionParams.setConnectionTimeout(params, connectionTimeout);
+ }
+
+ public void setStaleCheckingEnabled (final boolean staleCheckingEnabled) {
+ HttpConnectionParams.setStaleCheckingEnabled(params, staleCheckingEnabled);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParams.java
new file mode 100644
index 000000000..2efae2c37
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpConnectionParams.java
@@ -0,0 +1,243 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Utility class for accessing connection parameters in {@link HttpParams}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public final class HttpConnectionParams implements CoreConnectionPNames {
+
+ private HttpConnectionParams() {
+ super();
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#SO_TIMEOUT} parameter.
+ * If not set, defaults to <code>0</code>.
+ *
+ * @param params HTTP parameters.
+ * @return SO_TIMEOUT.
+ */
+ public static int getSoTimeout(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#SO_TIMEOUT} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param timeout SO_TIMEOUT.
+ */
+ public static void setSoTimeout(final HttpParams params, final int timeout) {
+ Args.notNull(params, "HTTP parameters");
+ params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);
+
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#SO_REUSEADDR} parameter.
+ * If not set, defaults to <code>false</code>.
+ *
+ * @param params HTTP parameters.
+ * @return SO_REUSEADDR.
+ *
+ * @since 4.1
+ */
+ public static boolean getSoReuseaddr(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getBooleanParameter(CoreConnectionPNames.SO_REUSEADDR, false);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#SO_REUSEADDR} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param reuseaddr SO_REUSEADDR.
+ *
+ * @since 4.1
+ */
+ public static void setSoReuseaddr(final HttpParams params, final boolean reuseaddr) {
+ Args.notNull(params, "HTTP parameters");
+ params.setBooleanParameter(CoreConnectionPNames.SO_REUSEADDR, reuseaddr);
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#TCP_NODELAY} parameter.
+ * If not set, defaults to <code>true</code>.
+ *
+ * @param params HTTP parameters.
+ * @return Nagle's algorithm flag
+ */
+ public static boolean getTcpNoDelay(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#TCP_NODELAY} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param value Nagle's algorithm flag
+ */
+ public static void setTcpNoDelay(final HttpParams params, final boolean value) {
+ Args.notNull(params, "HTTP parameters");
+ params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, value);
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#SOCKET_BUFFER_SIZE}
+ * parameter. If not set, defaults to <code>-1</code>.
+ *
+ * @param params HTTP parameters.
+ * @return socket buffer size
+ */
+ public static int getSocketBufferSize(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, -1);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#SOCKET_BUFFER_SIZE}
+ * parameter.
+ *
+ * @param params HTTP parameters.
+ * @param size socket buffer size
+ */
+ public static void setSocketBufferSize(final HttpParams params, final int size) {
+ Args.notNull(params, "HTTP parameters");
+ params.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, size);
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#SO_LINGER} parameter.
+ * If not set, defaults to <code>-1</code>.
+ *
+ * @param params HTTP parameters.
+ * @return SO_LINGER.
+ */
+ public static int getLinger(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getIntParameter(CoreConnectionPNames.SO_LINGER, -1);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#SO_LINGER} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param value SO_LINGER.
+ */
+ public static void setLinger(final HttpParams params, final int value) {
+ Args.notNull(params, "HTTP parameters");
+ params.setIntParameter(CoreConnectionPNames.SO_LINGER, value);
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#CONNECTION_TIMEOUT}
+ * parameter. If not set, defaults to <code>0</code>.
+ *
+ * @param params HTTP parameters.
+ * @return connect timeout.
+ */
+ public static int getConnectionTimeout(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 0);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#CONNECTION_TIMEOUT}
+ * parameter.
+ *
+ * @param params HTTP parameters.
+ * @param timeout connect timeout.
+ */
+ public static void setConnectionTimeout(final HttpParams params, final int timeout) {
+ Args.notNull(params, "HTTP parameters");
+ params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout);
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#STALE_CONNECTION_CHECK}
+ * parameter. If not set, defaults to <code>true</code>.
+ *
+ * @param params HTTP parameters.
+ * @return stale connection check flag.
+ */
+ public static boolean isStaleCheckingEnabled(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, true);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#STALE_CONNECTION_CHECK}
+ * parameter.
+ *
+ * @param params HTTP parameters.
+ * @param value stale connection check flag.
+ */
+ public static void setStaleCheckingEnabled(final HttpParams params, final boolean value) {
+ Args.notNull(params, "HTTP parameters");
+ params.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, value);
+ }
+
+ /**
+ * Obtains value of the {@link CoreConnectionPNames#SO_KEEPALIVE} parameter.
+ * If not set, defaults to <code>false</code>.
+ *
+ * @param params HTTP parameters.
+ * @return SO_KEEPALIVE.
+ *
+ * @since 4.2
+ */
+ public static boolean getSoKeepalive(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getBooleanParameter(CoreConnectionPNames.SO_KEEPALIVE, false);
+ }
+
+ /**
+ * Sets value of the {@link CoreConnectionPNames#SO_KEEPALIVE} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param enableKeepalive SO_KEEPALIVE.
+ *
+ * @since 4.2
+ */
+ public static void setSoKeepalive(final HttpParams params, final boolean enableKeepalive) {
+ Args.notNull(params, "HTTP parameters");
+ params.setBooleanParameter(CoreConnectionPNames.SO_KEEPALIVE, enableKeepalive);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamConfig.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamConfig.java
new file mode 100644
index 000000000..91a62a657
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamConfig.java
@@ -0,0 +1,78 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CodingErrorAction;
+
+import ch.boye.httpclientandroidlib.config.ConnectionConfig;
+import ch.boye.httpclientandroidlib.config.MessageConstraints;
+import ch.boye.httpclientandroidlib.config.SocketConfig;
+
+/**
+ * @deprecated (4.3) provided for compatibility with {@link HttpParams}. Do not use.
+ *
+ * @since 4.3
+ */
+@Deprecated
+public final class HttpParamConfig {
+
+ private HttpParamConfig() {
+ }
+
+ public static SocketConfig getSocketConfig(final HttpParams params) {
+ return SocketConfig.custom()
+ .setSoTimeout(params.getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0))
+ .setSoReuseAddress(params.getBooleanParameter(CoreConnectionPNames.SO_REUSEADDR, false))
+ .setSoKeepAlive(params.getBooleanParameter(CoreConnectionPNames.SO_KEEPALIVE, false))
+ .setSoLinger(params.getIntParameter(CoreConnectionPNames.SO_LINGER, -1))
+ .setTcpNoDelay(params.getBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true))
+ .build();
+ }
+
+ public static MessageConstraints getMessageConstraints(final HttpParams params) {
+ return MessageConstraints.custom()
+ .setMaxHeaderCount(params.getIntParameter(CoreConnectionPNames.MAX_HEADER_COUNT, -1))
+ .setMaxLineLength(params.getIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, -1))
+ .build();
+ }
+
+ public static ConnectionConfig getConnectionConfig(final HttpParams params) {
+ final MessageConstraints messageConstraints = getMessageConstraints(params);
+ final String csname = (String) params.getParameter(CoreProtocolPNames.HTTP_ELEMENT_CHARSET);
+ return ConnectionConfig.custom()
+ .setCharset(csname != null ? Charset.forName(csname) : null)
+ .setMalformedInputAction((CodingErrorAction)
+ params.getParameter(CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION))
+ .setMalformedInputAction((CodingErrorAction)
+ params.getParameter(CoreProtocolPNames.HTTP_UNMAPPABLE_INPUT_ACTION))
+ .setMessageConstraints(messageConstraints)
+ .build();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParams.java
new file mode 100644
index 000000000..7eb780b37
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParams.java
@@ -0,0 +1,195 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+/**
+ * HttpParams interface represents a collection of immutable values that define
+ * a runtime behavior of a component. HTTP parameters should be simple objects:
+ * integers, doubles, strings, collections and objects that remain immutable
+ * at runtime. HttpParams is expected to be used in 'write once - read many' mode.
+ * Once initialized, HTTP parameters are not expected to mutate in
+ * the course of HTTP message processing.
+ * <p>
+ * The purpose of this interface is to define a behavior of other components.
+ * Usually each complex component has its own HTTP parameter collection.
+ * <p>
+ * Instances of this interface can be linked together to form a hierarchy.
+ * In the simplest form one set of parameters can use content of another one
+ * to obtain default values of parameters not present in the local set.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public interface HttpParams {
+
+ /**
+ * Obtains the value of the given parameter.
+ *
+ * @param name the parent name.
+ *
+ * @return an object that represents the value of the parameter,
+ * <code>null</code> if the parameter is not set or if it
+ * is explicitly set to <code>null</code>
+ *
+ * @see #setParameter(String, Object)
+ */
+ Object getParameter(String name);
+
+ /**
+ * Assigns the value to the parameter with the given name.
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setParameter(String name, Object value);
+
+ /**
+ * Creates a copy of these parameters.
+ *
+ * @return a new set of parameters holding the same values as this one
+ */
+ HttpParams copy();
+
+ /**
+ * Removes the parameter with the specified name.
+ *
+ * @param name parameter name
+ *
+ * @return true if the parameter existed and has been removed, false else.
+ */
+ boolean removeParameter(String name);
+
+ /**
+ * Returns a {@link Long} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Long} that represents the value of the parameter.
+ *
+ * @see #setLongParameter(String, long)
+ */
+ long getLongParameter(String name, long defaultValue);
+
+ /**
+ * Assigns a {@link Long} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setLongParameter(String name, long value);
+
+ /**
+ * Returns an {@link Integer} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Integer} that represents the value of the parameter.
+ *
+ * @see #setIntParameter(String, int)
+ */
+ int getIntParameter(String name, int defaultValue);
+
+ /**
+ * Assigns an {@link Integer} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setIntParameter(String name, int value);
+
+ /**
+ * Returns a {@link Double} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Double} that represents the value of the parameter.
+ *
+ * @see #setDoubleParameter(String, double)
+ */
+ double getDoubleParameter(String name, double defaultValue);
+
+ /**
+ * Assigns a {@link Double} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setDoubleParameter(String name, double value);
+
+ /**
+ * Returns a {@link Boolean} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Boolean} that represents the value of the parameter.
+ *
+ * @see #setBooleanParameter(String, boolean)
+ */
+ boolean getBooleanParameter(String name, boolean defaultValue);
+
+ /**
+ * Assigns a {@link Boolean} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setBooleanParameter(String name, boolean value);
+
+ /**
+ * Checks if a boolean parameter is set to <code>true</code>.
+ *
+ * @param name parameter name
+ *
+ * @return <tt>true</tt> if the parameter is set to value <tt>true</tt>,
+ * <tt>false</tt> if it is not set or set to <code>false</code>
+ */
+ boolean isParameterTrue(String name);
+
+ /**
+ * Checks if a boolean parameter is not set or <code>false</code>.
+ *
+ * @param name parameter name
+ *
+ * @return <tt>true</tt> if the parameter is either not set or
+ * set to value <tt>false</tt>,
+ * <tt>false</tt> if it is set to <code>true</code>
+ */
+ boolean isParameterFalse(String name);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamsNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamsNames.java
new file mode 100644
index 000000000..0c4a34001
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpParamsNames.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import java.util.Set;
+
+/**
+ * Gives access to the full set of parameter names.
+ *
+ * @see HttpParams
+ *
+ * @since 4.2
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public interface HttpParamsNames {
+
+ /**
+ * Returns the current set of names;
+ * in the case of stacked parameters, returns the names
+ * from all the participating HttpParams instances.
+ *
+ * Changes to the underlying HttpParams are not reflected
+ * in the set - it is a snapshot.
+ *
+ * @return the names, as a Set<String>
+ */
+ Set<String> getNames();
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParamBean.java
new file mode 100644
index 000000000..368bffd5e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParamBean.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import ch.boye.httpclientandroidlib.HttpVersion;
+
+/**
+ * This is a Java Bean class that can be used to wrap an instance of
+ * {@link HttpParams} and manipulate HTTP protocol parameters using Java Beans
+ * conventions.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public class HttpProtocolParamBean extends HttpAbstractParamBean {
+
+ public HttpProtocolParamBean (final HttpParams params) {
+ super(params);
+ }
+
+ public void setHttpElementCharset (final String httpElementCharset) {
+ HttpProtocolParams.setHttpElementCharset(params, httpElementCharset);
+ }
+
+ public void setContentCharset (final String contentCharset) {
+ HttpProtocolParams.setContentCharset(params, contentCharset);
+ }
+
+ public void setVersion (final HttpVersion version) {
+ HttpProtocolParams.setVersion(params, version);
+ }
+
+ public void setUserAgent (final String userAgent) {
+ HttpProtocolParams.setUserAgent(params, userAgent);
+ }
+
+ public void setUseExpectContinue (final boolean useExpectContinue) {
+ HttpProtocolParams.setUseExpectContinue(params, useExpectContinue);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParams.java
new file mode 100644
index 000000000..2ef3e53ee
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/HttpProtocolParams.java
@@ -0,0 +1,240 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.params;
+
+import java.nio.charset.CodingErrorAction;
+
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Utility class for accessing protocol parameters in {@link HttpParams}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@Deprecated
+public final class HttpProtocolParams implements CoreProtocolPNames {
+
+ private HttpProtocolParams() {
+ super();
+ }
+
+ /**
+ * Obtains value of the {@link CoreProtocolPNames#HTTP_ELEMENT_CHARSET} parameter.
+ * If not set, defaults to <code>US-ASCII</code>.
+ *
+ * @param params HTTP parameters.
+ * @return HTTP element charset.
+ */
+ public static String getHttpElementCharset(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ String charset = (String) params.getParameter
+ (CoreProtocolPNames.HTTP_ELEMENT_CHARSET);
+ if (charset == null) {
+ charset = HTTP.DEF_PROTOCOL_CHARSET.name();
+ }
+ return charset;
+ }
+
+ /**
+ * Sets value of the {@link CoreProtocolPNames#HTTP_ELEMENT_CHARSET} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param charset HTTP element charset.
+ */
+ public static void setHttpElementCharset(final HttpParams params, final String charset) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(CoreProtocolPNames.HTTP_ELEMENT_CHARSET, charset);
+ }
+
+ /**
+ * Obtains value of the {@link CoreProtocolPNames#HTTP_CONTENT_CHARSET} parameter.
+ * If not set, defaults to <code>ISO-8859-1</code>.
+ *
+ * @param params HTTP parameters.
+ * @return HTTP content charset.
+ */
+ public static String getContentCharset(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ String charset = (String) params.getParameter
+ (CoreProtocolPNames.HTTP_CONTENT_CHARSET);
+ if (charset == null) {
+ charset = HTTP.DEF_CONTENT_CHARSET.name();
+ }
+ return charset;
+ }
+
+ /**
+ * Sets value of the {@link CoreProtocolPNames#HTTP_CONTENT_CHARSET} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param charset HTTP content charset.
+ */
+ public static void setContentCharset(final HttpParams params, final String charset) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, charset);
+ }
+
+ /**
+ * Obtains value of the {@link CoreProtocolPNames#PROTOCOL_VERSION} parameter.
+ * If not set, defaults to {@link HttpVersion#HTTP_1_1}.
+ *
+ * @param params HTTP parameters.
+ * @return HTTP protocol version.
+ */
+ public static ProtocolVersion getVersion(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ final Object param = params.getParameter
+ (CoreProtocolPNames.PROTOCOL_VERSION);
+ if (param == null) {
+ return HttpVersion.HTTP_1_1;
+ }
+ return (ProtocolVersion)param;
+ }
+
+ /**
+ * Sets value of the {@link CoreProtocolPNames#PROTOCOL_VERSION} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param version HTTP protocol version.
+ */
+ public static void setVersion(final HttpParams params, final ProtocolVersion version) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, version);
+ }
+
+ /**
+ * Obtains value of the {@link CoreProtocolPNames#USER_AGENT} parameter.
+ * If not set, returns <code>null</code>.
+ *
+ * @param params HTTP parameters.
+ * @return User agent string.
+ */
+ public static String getUserAgent(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return (String) params.getParameter(CoreProtocolPNames.USER_AGENT);
+ }
+
+ /**
+ * Sets value of the {@link CoreProtocolPNames#USER_AGENT} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param useragent User agent string.
+ */
+ public static void setUserAgent(final HttpParams params, final String useragent) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(CoreProtocolPNames.USER_AGENT, useragent);
+ }
+
+ /**
+ * Obtains value of the {@link CoreProtocolPNames#USE_EXPECT_CONTINUE} parameter.
+ * If not set, returns <code>false</code>.
+ *
+ * @param params HTTP parameters.
+ * @return User agent string.
+ */
+ public static boolean useExpectContinue(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ return params.getBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
+ }
+
+ /**
+ * Sets value of the {@link CoreProtocolPNames#USE_EXPECT_CONTINUE} parameter.
+ *
+ * @param params HTTP parameters.
+ * @param b expect-continue flag.
+ */
+ public static void setUseExpectContinue(final HttpParams params, final boolean b) {
+ Args.notNull(params, "HTTP parameters");
+ params.setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, b);
+ }
+
+ /**
+ * Obtains value of the {@link CoreProtocolPNames#HTTP_MALFORMED_INPUT_ACTION} parameter.
+ * @param params HTTP parameters.
+ * @return Action to perform upon receiving a malformed input
+ *
+ * @since 4.2
+ */
+ public static CodingErrorAction getMalformedInputAction(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ final Object param = params.getParameter(CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION);
+ if (param == null) {
+ // the default CodingErrorAction
+ return CodingErrorAction.REPORT;
+ }
+ return (CodingErrorAction) param;
+ }
+
+ /**
+ * Sets value of the {@link CoreProtocolPNames#HTTP_MALFORMED_INPUT_ACTION} parameter.
+ * @param params HTTP parameters
+ * @param action action to perform on malformed inputs
+ *
+ * @since 4.2
+ */
+ public static void setMalformedInputAction(final HttpParams params, final CodingErrorAction action) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION, action);
+ }
+
+ /**
+ * Obtains the value of the {@link CoreProtocolPNames#HTTP_UNMAPPABLE_INPUT_ACTION} parameter.
+ * @param params HTTP parameters
+ * @return Action to perform upon receiving a unmapped input
+ *
+ * @since 4.2
+ */
+ public static CodingErrorAction getUnmappableInputAction(final HttpParams params) {
+ Args.notNull(params, "HTTP parameters");
+ final Object param = params.getParameter(CoreProtocolPNames.HTTP_UNMAPPABLE_INPUT_ACTION);
+ if (param == null) {
+ // the default CodingErrorAction
+ return CodingErrorAction.REPORT;
+ }
+ return (CodingErrorAction) param;
+ }
+
+ /**
+ * Sets the value of the {@link CoreProtocolPNames#HTTP_UNMAPPABLE_INPUT_ACTION} parameter.
+ * @param params HTTP parameters
+ * @param action action to perform on un mappable inputs
+ *
+ * @since 4.2
+ */
+ public static void setUnmappableInputAction(final HttpParams params, final CodingErrorAction action) {
+ Args.notNull(params, "HTTP parameters");
+ params.setParameter(CoreProtocolPNames.HTTP_UNMAPPABLE_INPUT_ACTION, action);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/SyncBasicHttpParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/SyncBasicHttpParams.java
new file mode 100644
index 000000000..30393a074
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/SyncBasicHttpParams.java
@@ -0,0 +1,89 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.params;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+/**
+ * Thread-safe extension of the {@link BasicHttpParams}.
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.3) use configuration classes provided 'ch.boye.httpclientandroidlib.config'
+ * and 'ch.boye.httpclientandroidlib.client.config'
+ */
+@ThreadSafe
+@Deprecated
+public class SyncBasicHttpParams extends BasicHttpParams {
+
+ private static final long serialVersionUID = 5387834869062660642L;
+
+ public SyncBasicHttpParams() {
+ super();
+ }
+
+ @Override
+ public synchronized boolean removeParameter(final String name) {
+ return super.removeParameter(name);
+ }
+
+ @Override
+ public synchronized HttpParams setParameter(final String name, final Object value) {
+ return super.setParameter(name, value);
+ }
+
+ @Override
+ public synchronized Object getParameter(final String name) {
+ return super.getParameter(name);
+ }
+
+ @Override
+ public synchronized boolean isParameterSet(final String name) {
+ return super.isParameterSet(name);
+ }
+
+ @Override
+ public synchronized boolean isParameterSetLocally(final String name) {
+ return super.isParameterSetLocally(name);
+ }
+
+ @Override
+ public synchronized void setParameters(final String[] names, final Object value) {
+ super.setParameters(names, value);
+ }
+
+ @Override
+ public synchronized void clear() {
+ super.clear();
+ }
+
+ @Override
+ public synchronized Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/package-info.java
new file mode 100644
index 000000000..0589b0ff9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/params/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Deprecated.
+ * @deprecated (4.3).
+ */
+package ch.boye.httpclientandroidlib.params;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/AbstractConnPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/AbstractConnPool.java
new file mode 100644
index 000000000..35aeb656f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/AbstractConnPool.java
@@ -0,0 +1,533 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.concurrent.FutureCallback;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+/**
+ * Abstract synchronous (blocking) pool of connections.
+ * <p/>
+ * Please note that this class does not maintain its own pool of execution {@link Thread}s.
+ * Therefore, one <b>must</b> call {@link Future#get()} or {@link Future#get(long, TimeUnit)}
+ * method on the {@link Future} object returned by the
+ * {@link #lease(Object, Object, FutureCallback)} method in order for the lease operation
+ * to complete.
+ *
+ * @param <T> the route type that represents the opposite endpoint of a pooled
+ * connection.
+ * @param <C> the connection type.
+ * @param <E> the type of the pool entry containing a pooled connection.
+ * @since 4.2
+ */
+@ThreadSafe
+public abstract class AbstractConnPool<T, C, E extends PoolEntry<T, C>>
+ implements ConnPool<T, E>, ConnPoolControl<T> {
+
+ private final Lock lock;
+ private final ConnFactory<T, C> connFactory;
+ private final Map<T, RouteSpecificPool<T, C, E>> routeToPool;
+ private final Set<E> leased;
+ private final LinkedList<E> available;
+ private final LinkedList<PoolEntryFuture<E>> pending;
+ private final Map<T, Integer> maxPerRoute;
+
+ private volatile boolean isShutDown;
+ private volatile int defaultMaxPerRoute;
+ private volatile int maxTotal;
+
+ public AbstractConnPool(
+ final ConnFactory<T, C> connFactory,
+ final int defaultMaxPerRoute,
+ final int maxTotal) {
+ super();
+ this.connFactory = Args.notNull(connFactory, "Connection factory");
+ this.defaultMaxPerRoute = Args.notNegative(defaultMaxPerRoute, "Max per route value");
+ this.maxTotal = Args.notNegative(maxTotal, "Max total value");
+ this.lock = new ReentrantLock();
+ this.routeToPool = new HashMap<T, RouteSpecificPool<T, C, E>>();
+ this.leased = new HashSet<E>();
+ this.available = new LinkedList<E>();
+ this.pending = new LinkedList<PoolEntryFuture<E>>();
+ this.maxPerRoute = new HashMap<T, Integer>();
+ }
+
+ /**
+ * Creates a new entry for the given connection with the given route.
+ */
+ protected abstract E createEntry(T route, C conn);
+
+ /**
+ * @since 4.3
+ */
+ protected void onLease(final E entry) {
+ }
+
+ /**
+ * @since 4.3
+ */
+ protected void onRelease(final E entry) {
+ }
+
+ public boolean isShutdown() {
+ return this.isShutDown;
+ }
+
+ /**
+ * Shuts down the pool.
+ */
+ public void shutdown() throws IOException {
+ if (this.isShutDown) {
+ return ;
+ }
+ this.isShutDown = true;
+ this.lock.lock();
+ try {
+ for (final E entry: this.available) {
+ entry.close();
+ }
+ for (final E entry: this.leased) {
+ entry.close();
+ }
+ for (final RouteSpecificPool<T, C, E> pool: this.routeToPool.values()) {
+ pool.shutdown();
+ }
+ this.routeToPool.clear();
+ this.leased.clear();
+ this.available.clear();
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ private RouteSpecificPool<T, C, E> getPool(final T route) {
+ RouteSpecificPool<T, C, E> pool = this.routeToPool.get(route);
+ if (pool == null) {
+ pool = new RouteSpecificPool<T, C, E>(route) {
+
+ @Override
+ protected E createEntry(final C conn) {
+ return AbstractConnPool.this.createEntry(route, conn);
+ }
+
+ };
+ this.routeToPool.put(route, pool);
+ }
+ return pool;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Please note that this class does not maintain its own pool of execution
+ * {@link Thread}s. Therefore, one <b>must</b> call {@link Future#get()}
+ * or {@link Future#get(long, TimeUnit)} method on the {@link Future}
+ * returned by this method in order for the lease operation to complete.
+ */
+ public Future<E> lease(final T route, final Object state, final FutureCallback<E> callback) {
+ Args.notNull(route, "Route");
+ Asserts.check(!this.isShutDown, "Connection pool shut down");
+ return new PoolEntryFuture<E>(this.lock, callback) {
+
+ @Override
+ public E getPoolEntry(
+ final long timeout,
+ final TimeUnit tunit)
+ throws InterruptedException, TimeoutException, IOException {
+ final E entry = getPoolEntryBlocking(route, state, timeout, tunit, this);
+ onLease(entry);
+ return entry;
+ }
+
+ };
+ }
+
+ /**
+ * Attempts to lease a connection for the given route and with the given
+ * state from the pool.
+ * <p/>
+ * Please note that this class does not maintain its own pool of execution
+ * {@link Thread}s. Therefore, one <b>must</b> call {@link Future#get()}
+ * or {@link Future#get(long, TimeUnit)} method on the {@link Future}
+ * returned by this method in order for the lease operation to complete.
+ *
+ * @param route route of the connection.
+ * @param state arbitrary object that represents a particular state
+ * (usually a security principal or a unique token identifying
+ * the user whose credentials have been used while establishing the connection).
+ * May be <code>null</code>.
+ * @return future for a leased pool entry.
+ */
+ public Future<E> lease(final T route, final Object state) {
+ return lease(route, state, null);
+ }
+
+ private E getPoolEntryBlocking(
+ final T route, final Object state,
+ final long timeout, final TimeUnit tunit,
+ final PoolEntryFuture<E> future)
+ throws IOException, InterruptedException, TimeoutException {
+
+ Date deadline = null;
+ if (timeout > 0) {
+ deadline = new Date
+ (System.currentTimeMillis() + tunit.toMillis(timeout));
+ }
+
+ this.lock.lock();
+ try {
+ final RouteSpecificPool<T, C, E> pool = getPool(route);
+ E entry = null;
+ while (entry == null) {
+ Asserts.check(!this.isShutDown, "Connection pool shut down");
+ for (;;) {
+ entry = pool.getFree(state);
+ if (entry == null) {
+ break;
+ }
+ if (entry.isClosed() || entry.isExpired(System.currentTimeMillis())) {
+ entry.close();
+ this.available.remove(entry);
+ pool.free(entry, false);
+ } else {
+ break;
+ }
+ }
+ if (entry != null) {
+ this.available.remove(entry);
+ this.leased.add(entry);
+ return entry;
+ }
+
+ // New connection is needed
+ final int maxPerRoute = getMax(route);
+ // Shrink the pool prior to allocating a new connection
+ final int excess = Math.max(0, pool.getAllocatedCount() + 1 - maxPerRoute);
+ if (excess > 0) {
+ for (int i = 0; i < excess; i++) {
+ final E lastUsed = pool.getLastUsed();
+ if (lastUsed == null) {
+ break;
+ }
+ lastUsed.close();
+ this.available.remove(lastUsed);
+ pool.remove(lastUsed);
+ }
+ }
+
+ if (pool.getAllocatedCount() < maxPerRoute) {
+ final int totalUsed = this.leased.size();
+ final int freeCapacity = Math.max(this.maxTotal - totalUsed, 0);
+ if (freeCapacity > 0) {
+ final int totalAvailable = this.available.size();
+ if (totalAvailable > freeCapacity - 1) {
+ if (!this.available.isEmpty()) {
+ final E lastUsed = this.available.removeLast();
+ lastUsed.close();
+ final RouteSpecificPool<T, C, E> otherpool = getPool(lastUsed.getRoute());
+ otherpool.remove(lastUsed);
+ }
+ }
+ final C conn = this.connFactory.create(route);
+ entry = pool.add(conn);
+ this.leased.add(entry);
+ return entry;
+ }
+ }
+
+ boolean success = false;
+ try {
+ pool.queue(future);
+ this.pending.add(future);
+ success = future.await(deadline);
+ } finally {
+ // In case of 'success', we were woken up by the
+ // connection pool and should now have a connection
+ // waiting for us, or else we're shutting down.
+ // Just continue in the loop, both cases are checked.
+ pool.unqueue(future);
+ this.pending.remove(future);
+ }
+ // check for spurious wakeup vs. timeout
+ if (!success && (deadline != null) &&
+ (deadline.getTime() <= System.currentTimeMillis())) {
+ break;
+ }
+ }
+ throw new TimeoutException("Timeout waiting for connection");
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void release(final E entry, final boolean reusable) {
+ this.lock.lock();
+ try {
+ if (this.leased.remove(entry)) {
+ final RouteSpecificPool<T, C, E> pool = getPool(entry.getRoute());
+ pool.free(entry, reusable);
+ if (reusable && !this.isShutDown) {
+ this.available.addFirst(entry);
+ onRelease(entry);
+ } else {
+ entry.close();
+ }
+ PoolEntryFuture<E> future = pool.nextPending();
+ if (future != null) {
+ this.pending.remove(future);
+ } else {
+ future = this.pending.poll();
+ }
+ if (future != null) {
+ future.wakeup();
+ }
+ }
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ private int getMax(final T route) {
+ final Integer v = this.maxPerRoute.get(route);
+ if (v != null) {
+ return v.intValue();
+ } else {
+ return this.defaultMaxPerRoute;
+ }
+ }
+
+ public void setMaxTotal(final int max) {
+ Args.notNegative(max, "Max value");
+ this.lock.lock();
+ try {
+ this.maxTotal = max;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public int getMaxTotal() {
+ this.lock.lock();
+ try {
+ return this.maxTotal;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void setDefaultMaxPerRoute(final int max) {
+ Args.notNegative(max, "Max per route value");
+ this.lock.lock();
+ try {
+ this.defaultMaxPerRoute = max;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public int getDefaultMaxPerRoute() {
+ this.lock.lock();
+ try {
+ return this.defaultMaxPerRoute;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void setMaxPerRoute(final T route, final int max) {
+ Args.notNull(route, "Route");
+ Args.notNegative(max, "Max per route value");
+ this.lock.lock();
+ try {
+ this.maxPerRoute.put(route, Integer.valueOf(max));
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public int getMaxPerRoute(final T route) {
+ Args.notNull(route, "Route");
+ this.lock.lock();
+ try {
+ return getMax(route);
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public PoolStats getTotalStats() {
+ this.lock.lock();
+ try {
+ return new PoolStats(
+ this.leased.size(),
+ this.pending.size(),
+ this.available.size(),
+ this.maxTotal);
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public PoolStats getStats(final T route) {
+ Args.notNull(route, "Route");
+ this.lock.lock();
+ try {
+ final RouteSpecificPool<T, C, E> pool = getPool(route);
+ return new PoolStats(
+ pool.getLeasedCount(),
+ pool.getPendingCount(),
+ pool.getAvailableCount(),
+ getMax(route));
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ /**
+ * Enumerates all available connections.
+ *
+ * @since 4.3
+ */
+ protected void enumAvailable(final PoolEntryCallback<T, C> callback) {
+ this.lock.lock();
+ try {
+ final Iterator<E> it = this.available.iterator();
+ while (it.hasNext()) {
+ final E entry = it.next();
+ callback.process(entry);
+ if (entry.isClosed()) {
+ final RouteSpecificPool<T, C, E> pool = getPool(entry.getRoute());
+ pool.remove(entry);
+ it.remove();
+ }
+ }
+ purgePoolMap();
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ /**
+ * Enumerates all leased connections.
+ *
+ * @since 4.3
+ */
+ protected void enumLeased(final PoolEntryCallback<T, C> callback) {
+ this.lock.lock();
+ try {
+ final Iterator<E> it = this.leased.iterator();
+ while (it.hasNext()) {
+ final E entry = it.next();
+ callback.process(entry);
+ }
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ private void purgePoolMap() {
+ final Iterator<Map.Entry<T, RouteSpecificPool<T, C, E>>> it = this.routeToPool.entrySet().iterator();
+ while (it.hasNext()) {
+ final Map.Entry<T, RouteSpecificPool<T, C, E>> entry = it.next();
+ final RouteSpecificPool<T, C, E> pool = entry.getValue();
+ if (pool.getPendingCount() + pool.getAllocatedCount() == 0) {
+ it.remove();
+ }
+ }
+ }
+
+ /**
+ * Closes connections that have been idle longer than the given period
+ * of time and evicts them from the pool.
+ *
+ * @param idletime maximum idle time.
+ * @param tunit time unit.
+ */
+ public void closeIdle(final long idletime, final TimeUnit tunit) {
+ Args.notNull(tunit, "Time unit");
+ long time = tunit.toMillis(idletime);
+ if (time < 0) {
+ time = 0;
+ }
+ final long deadline = System.currentTimeMillis() - time;
+ enumAvailable(new PoolEntryCallback<T, C>() {
+
+ public void process(final PoolEntry<T, C> entry) {
+ if (entry.getUpdated() <= deadline) {
+ entry.close();
+ }
+ }
+
+ });
+ }
+
+ /**
+ * Closes expired connections and evicts them from the pool.
+ */
+ public void closeExpired() {
+ final long now = System.currentTimeMillis();
+ enumAvailable(new PoolEntryCallback<T, C>() {
+
+ public void process(final PoolEntry<T, C> entry) {
+ if (entry.isExpired(now)) {
+ entry.close();
+ }
+ }
+
+ });
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("[leased: ");
+ buffer.append(this.leased);
+ buffer.append("][available: ");
+ buffer.append(this.available);
+ buffer.append("][pending: ");
+ buffer.append(this.pending);
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnFactory.java
new file mode 100644
index 000000000..e2319639c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnFactory.java
@@ -0,0 +1,44 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.pool;
+
+import java.io.IOException;
+
+/**
+ * Factory for poolable blocking connections.
+ *
+ * @param <T> the route type that represents the opposite endpoint of a pooled
+ * connection.
+ * @param <C> the connection type.
+ * @since 4.2
+ */
+public interface ConnFactory<T, C> {
+
+ C create(T route) throws IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPool.java
new file mode 100644
index 000000000..803ecda88
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPool.java
@@ -0,0 +1,68 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+import java.util.concurrent.Future;
+
+import ch.boye.httpclientandroidlib.concurrent.FutureCallback;
+
+/**
+ * <tt>ConnPool</tt> represents a shared pool connections can be leased from
+ * and released back to.
+ *
+ * @param <T> the route type that represents the opposite endpoint of a pooled
+ * connection.
+ * @param <E> the type of the pool entry containing a pooled connection.
+ * @since 4.2
+ */
+public interface ConnPool<T, E> {
+
+ /**
+ * Attempts to lease a connection for the given route and with the given
+ * state from the pool.
+ *
+ * @param route route of the connection.
+ * @param state arbitrary object that represents a particular state
+ * (usually a security principal or a unique token identifying
+ * the user whose credentials have been used while establishing the connection).
+ * May be <code>null</code>.
+ * @param callback operation completion callback.
+ *
+ * @return future for a leased pool entry.
+ */
+ Future<E> lease(final T route, final Object state, final FutureCallback<E> callback);
+
+ /**
+ * Releases the pool entry back to the pool.
+ *
+ * @param entry pool entry leased from the pool
+ * @param reusable flag indicating whether or not the released connection
+ * is in a consistent state and is safe for further use.
+ */
+ void release(E entry, boolean reusable);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPoolControl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPoolControl.java
new file mode 100644
index 000000000..841ba7ccc
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/ConnPoolControl.java
@@ -0,0 +1,56 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+/**
+ * Interface to control runtime properties of a {@link ConnPool} such as
+ * maximum total number of connections or maximum connections per route
+ * allowed.
+ *
+ * @param <T> the route type that represents the opposite endpoint of a pooled
+ * connection.
+ * @since 4.2
+ */
+public interface ConnPoolControl<T> {
+
+ void setMaxTotal(int max);
+
+ int getMaxTotal();
+
+ void setDefaultMaxPerRoute(int max);
+
+ int getDefaultMaxPerRoute();
+
+ void setMaxPerRoute(final T route, int max);
+
+ int getMaxPerRoute(final T route);
+
+ PoolStats getTotalStats();
+
+ PoolStats getStats(final T route);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntry.java
new file mode 100644
index 000000000..db52afb6f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntry.java
@@ -0,0 +1,183 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+import java.util.concurrent.TimeUnit;
+
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Pool entry containing a pool connection object along with its route.
+ * <p/>
+ * The connection contained by the pool entry may have an expiration time which
+ * can be either set upon construction time or updated with
+ * the {@link #updateExpiry(long, TimeUnit)}.
+ * <p/>
+ * Pool entry may also have an object associated with it that represents
+ * a connection state (usually a security principal or a unique token identifying
+ * the user whose credentials have been used while establishing the connection).
+ *
+ * @param <T> the route type that represents the opposite endpoint of a pooled
+ * connection.
+ * @param <C> the connection type.
+ * @since 4.2
+ */
+@ThreadSafe
+public abstract class PoolEntry<T, C> {
+
+ private final String id;
+ private final T route;
+ private final C conn;
+ private final long created;
+ private final long validUnit;
+
+ @GuardedBy("this")
+ private long updated;
+
+ @GuardedBy("this")
+ private long expiry;
+
+ private volatile Object state;
+
+ /**
+ * Creates new <tt>PoolEntry</tt> instance.
+ *
+ * @param id unique identifier of the pool entry. May be <code>null</code>.
+ * @param route route to the opposite endpoint.
+ * @param conn the connection.
+ * @param timeToLive maximum time to live. May be zero if the connection
+ * does not have an expiry deadline.
+ * @param tunit time unit.
+ */
+ public PoolEntry(final String id, final T route, final C conn,
+ final long timeToLive, final TimeUnit tunit) {
+ super();
+ Args.notNull(route, "Route");
+ Args.notNull(conn, "Connection");
+ Args.notNull(tunit, "Time unit");
+ this.id = id;
+ this.route = route;
+ this.conn = conn;
+ this.created = System.currentTimeMillis();
+ if (timeToLive > 0) {
+ this.validUnit = this.created + tunit.toMillis(timeToLive);
+ } else {
+ this.validUnit = Long.MAX_VALUE;
+ }
+ this.expiry = this.validUnit;
+ }
+
+ /**
+ * Creates new <tt>PoolEntry</tt> instance without an expiry deadline.
+ *
+ * @param id unique identifier of the pool entry. May be <code>null</code>.
+ * @param route route to the opposite endpoint.
+ * @param conn the connection.
+ */
+ public PoolEntry(final String id, final T route, final C conn) {
+ this(id, route, conn, 0, TimeUnit.MILLISECONDS);
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ public T getRoute() {
+ return this.route;
+ }
+
+ public C getConnection() {
+ return this.conn;
+ }
+
+ public long getCreated() {
+ return this.created;
+ }
+
+ public long getValidUnit() {
+ return this.validUnit;
+ }
+
+ public Object getState() {
+ return this.state;
+ }
+
+ public void setState(final Object state) {
+ this.state = state;
+ }
+
+ public synchronized long getUpdated() {
+ return this.updated;
+ }
+
+ public synchronized long getExpiry() {
+ return this.expiry;
+ }
+
+ public synchronized void updateExpiry(final long time, final TimeUnit tunit) {
+ Args.notNull(tunit, "Time unit");
+ this.updated = System.currentTimeMillis();
+ final long newExpiry;
+ if (time > 0) {
+ newExpiry = this.updated + tunit.toMillis(time);
+ } else {
+ newExpiry = Long.MAX_VALUE;
+ }
+ this.expiry = Math.min(newExpiry, this.validUnit);
+ }
+
+ public synchronized boolean isExpired(final long now) {
+ return now >= this.expiry;
+ }
+
+ /**
+ * Invalidates the pool entry and closes the pooled connection associated
+ * with it.
+ */
+ public abstract void close();
+
+ /**
+ * Returns <code>true</code> if the pool entry has been invalidated.
+ */
+ public abstract boolean isClosed();
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("[id:");
+ buffer.append(this.id);
+ buffer.append("][route:");
+ buffer.append(this.route);
+ buffer.append("][state:");
+ buffer.append(this.state);
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryCallback.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryCallback.java
new file mode 100644
index 000000000..5c70d63da
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryCallback.java
@@ -0,0 +1,41 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+/**
+ * Pool entry callabck.
+ *
+ * @param <T> the route type that represents the opposite endpoint of a pooled
+ * connection.
+ * @param <C> the connection type.
+ * @since 4.3
+ */
+public interface PoolEntryCallback<T, C> {
+
+ void process(PoolEntry<T, C> entry);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryFuture.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryFuture.java
new file mode 100644
index 000000000..743abe8c0
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolEntryFuture.java
@@ -0,0 +1,155 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.concurrent.FutureCallback;
+import ch.boye.httpclientandroidlib.util.Args;
+
+@ThreadSafe
+abstract class PoolEntryFuture<T> implements Future<T> {
+
+ private final Lock lock;
+ private final FutureCallback<T> callback;
+ private final Condition condition;
+ private volatile boolean cancelled;
+ private volatile boolean completed;
+ private T result;
+
+ PoolEntryFuture(final Lock lock, final FutureCallback<T> callback) {
+ super();
+ this.lock = lock;
+ this.condition = lock.newCondition();
+ this.callback = callback;
+ }
+
+ public boolean cancel(final boolean mayInterruptIfRunning) {
+ this.lock.lock();
+ try {
+ if (this.completed) {
+ return false;
+ }
+ this.completed = true;
+ this.cancelled = true;
+ if (this.callback != null) {
+ this.callback.cancelled();
+ }
+ this.condition.signalAll();
+ return true;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ public boolean isDone() {
+ return this.completed;
+ }
+
+ public T get() throws InterruptedException, ExecutionException {
+ try {
+ return get(0, TimeUnit.MILLISECONDS);
+ } catch (final TimeoutException ex) {
+ throw new ExecutionException(ex);
+ }
+ }
+
+ public T get(
+ final long timeout,
+ final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ Args.notNull(unit, "Time unit");
+ this.lock.lock();
+ try {
+ if (this.completed) {
+ return this.result;
+ }
+ this.result = getPoolEntry(timeout, unit);
+ this.completed = true;
+ if (this.callback != null) {
+ this.callback.completed(this.result);
+ }
+ return result;
+ } catch (final IOException ex) {
+ this.completed = true;
+ this.result = null;
+ if (this.callback != null) {
+ this.callback.failed(ex);
+ }
+ throw new ExecutionException(ex);
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ protected abstract T getPoolEntry(
+ long timeout, TimeUnit unit) throws IOException, InterruptedException, TimeoutException;
+
+ public boolean await(final Date deadline) throws InterruptedException {
+ this.lock.lock();
+ try {
+ if (this.cancelled) {
+ throw new InterruptedException("Operation interrupted");
+ }
+ final boolean success;
+ if (deadline != null) {
+ success = this.condition.awaitUntil(deadline);
+ } else {
+ this.condition.await();
+ success = true;
+ }
+ if (this.cancelled) {
+ throw new InterruptedException("Operation interrupted");
+ }
+ return success;
+ } finally {
+ this.lock.unlock();
+ }
+
+ }
+
+ public void wakeup() {
+ this.lock.lock();
+ try {
+ this.condition.signalAll();
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolStats.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolStats.java
new file mode 100644
index 000000000..17e948ee5
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/PoolStats.java
@@ -0,0 +1,114 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+
+/**
+ * Pool statistics.
+ * <p>
+ * The total number of connections in the pool is equal to {@code available} plus {@code leased}.
+ * </p>
+ *
+ * @since 4.2
+ */
+@Immutable
+public class PoolStats {
+
+ private final int leased;
+ private final int pending;
+ private final int available;
+ private final int max;
+
+ public PoolStats(final int leased, final int pending, final int free, final int max) {
+ super();
+ this.leased = leased;
+ this.pending = pending;
+ this.available = free;
+ this.max = max;
+ }
+
+ /**
+ * Gets the number of persistent connections tracked by the connection manager currently being used to execute
+ * requests.
+ * <p>
+ * The total number of connections in the pool is equal to {@code available} plus {@code leased}.
+ * </p>
+ *
+ * @return the number of persistent connections.
+ */
+ public int getLeased() {
+ return this.leased;
+ }
+
+ /**
+ * Gets the number of connection requests being blocked awaiting a free connection. This can happen only if there
+ * are more worker threads contending for fewer connections.
+ *
+ * @return the number of connection requests being blocked awaiting a free connection.
+ */
+ public int getPending() {
+ return this.pending;
+ }
+
+ /**
+ * Gets the number idle persistent connections.
+ * <p>
+ * The total number of connections in the pool is equal to {@code available} plus {@code leased}.
+ * </p>
+ *
+ * @return number idle persistent connections.
+ */
+ public int getAvailable() {
+ return this.available;
+ }
+
+ /**
+ * Gets the maximum number of allowed persistent connections.
+ *
+ * @return the maximum number of allowed persistent connections.
+ */
+ public int getMax() {
+ return this.max;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("[leased: ");
+ buffer.append(this.leased);
+ buffer.append("; pending: ");
+ buffer.append(this.pending);
+ buffer.append("; available: ");
+ buffer.append(this.available);
+ buffer.append("; max: ");
+ buffer.append(this.max);
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/RouteSpecificPool.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/RouteSpecificPool.java
new file mode 100644
index 000000000..7023f79aa
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/RouteSpecificPool.java
@@ -0,0 +1,184 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.pool;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Set;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.Asserts;
+
+@NotThreadSafe
+abstract class RouteSpecificPool<T, C, E extends PoolEntry<T, C>> {
+
+ private final T route;
+ private final Set<E> leased;
+ private final LinkedList<E> available;
+ private final LinkedList<PoolEntryFuture<E>> pending;
+
+ RouteSpecificPool(final T route) {
+ super();
+ this.route = route;
+ this.leased = new HashSet<E>();
+ this.available = new LinkedList<E>();
+ this.pending = new LinkedList<PoolEntryFuture<E>>();
+ }
+
+ protected abstract E createEntry(C conn);
+
+ public final T getRoute() {
+ return route;
+ }
+
+ public int getLeasedCount() {
+ return this.leased.size();
+ }
+
+ public int getPendingCount() {
+ return this.pending.size();
+ }
+
+ public int getAvailableCount() {
+ return this.available.size();
+ }
+
+ public int getAllocatedCount() {
+ return this.available.size() + this.leased.size();
+ }
+
+ public E getFree(final Object state) {
+ if (!this.available.isEmpty()) {
+ if (state != null) {
+ final Iterator<E> it = this.available.iterator();
+ while (it.hasNext()) {
+ final E entry = it.next();
+ if (state.equals(entry.getState())) {
+ it.remove();
+ this.leased.add(entry);
+ return entry;
+ }
+ }
+ }
+ final Iterator<E> it = this.available.iterator();
+ while (it.hasNext()) {
+ final E entry = it.next();
+ if (entry.getState() == null) {
+ it.remove();
+ this.leased.add(entry);
+ return entry;
+ }
+ }
+ }
+ return null;
+ }
+
+ public E getLastUsed() {
+ if (!this.available.isEmpty()) {
+ return this.available.getLast();
+ } else {
+ return null;
+ }
+ }
+
+ public boolean remove(final E entry) {
+ Args.notNull(entry, "Pool entry");
+ if (!this.available.remove(entry)) {
+ if (!this.leased.remove(entry)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void free(final E entry, final boolean reusable) {
+ Args.notNull(entry, "Pool entry");
+ final boolean found = this.leased.remove(entry);
+ Asserts.check(found, "Entry %s has not been leased from this pool", entry);
+ if (reusable) {
+ this.available.addFirst(entry);
+ }
+ }
+
+ public E add(final C conn) {
+ final E entry = createEntry(conn);
+ this.leased.add(entry);
+ return entry;
+ }
+
+ public void queue(final PoolEntryFuture<E> future) {
+ if (future == null) {
+ return;
+ }
+ this.pending.add(future);
+ }
+
+ public PoolEntryFuture<E> nextPending() {
+ return this.pending.poll();
+ }
+
+ public void unqueue(final PoolEntryFuture<E> future) {
+ if (future == null) {
+ return;
+ }
+
+ this.pending.remove(future);
+ }
+
+ public void shutdown() {
+ for (final PoolEntryFuture<E> future: this.pending) {
+ future.cancel(true);
+ }
+ this.pending.clear();
+ for (final E entry: this.available) {
+ entry.close();
+ }
+ this.available.clear();
+ for (final E entry: this.leased) {
+ entry.close();
+ }
+ this.leased.clear();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("[route: ");
+ buffer.append(this.route);
+ buffer.append("][leased: ");
+ buffer.append(this.leased.size());
+ buffer.append("][available: ");
+ buffer.append(this.available.size());
+ buffer.append("][pending: ");
+ buffer.append(this.pending.size());
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/package-info.java
new file mode 100644
index 000000000..fdca4e695
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/pool/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Client side connection pools APIs for synchronous, blocking
+ * communication.
+ */
+package ch.boye.httpclientandroidlib.pool;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpContext.java
new file mode 100644
index 000000000..72c247a5e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpContext.java
@@ -0,0 +1,95 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of {@link HttpContext}.
+ * <p>
+ * Please note instances of this class can be thread unsafe if the
+ * parent context is not thread safe.
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class BasicHttpContext implements HttpContext {
+
+ private final HttpContext parentContext;
+ private final Map<String, Object> map;
+
+ public BasicHttpContext() {
+ this(null);
+ }
+
+ public BasicHttpContext(final HttpContext parentContext) {
+ super();
+ this.map = new ConcurrentHashMap<String, Object>();
+ this.parentContext = parentContext;
+ }
+
+ public Object getAttribute(final String id) {
+ Args.notNull(id, "Id");
+ Object obj = this.map.get(id);
+ if (obj == null && this.parentContext != null) {
+ obj = this.parentContext.getAttribute(id);
+ }
+ return obj;
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ Args.notNull(id, "Id");
+ if (obj != null) {
+ this.map.put(id, obj);
+ } else {
+ this.map.remove(id);
+ }
+ }
+
+ public Object removeAttribute(final String id) {
+ Args.notNull(id, "Id");
+ return this.map.remove(id);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public void clear() {
+ this.map.clear();
+ }
+
+ @Override
+ public String toString() {
+ return this.map.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpProcessor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpProcessor.java
new file mode 100644
index 000000000..1fa203cef
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/BasicHttpProcessor.java
@@ -0,0 +1,246 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Default implementation of {@link HttpProcessor}.
+ * <p>
+ * Please note access to the internal structures of this class is not
+ * synchronized and therefore this class may be thread-unsafe.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3)
+ */
+@NotThreadSafe
+@Deprecated
+public final class BasicHttpProcessor implements
+ HttpProcessor, HttpRequestInterceptorList, HttpResponseInterceptorList, Cloneable {
+
+ // Don't allow direct access, as nulls are not allowed
+ protected final List<HttpRequestInterceptor> requestInterceptors = new ArrayList<HttpRequestInterceptor>();
+ protected final List<HttpResponseInterceptor> responseInterceptors = new ArrayList<HttpResponseInterceptor>();
+
+ public void addRequestInterceptor(final HttpRequestInterceptor itcp) {
+ if (itcp == null) {
+ return;
+ }
+ this.requestInterceptors.add(itcp);
+ }
+
+ public void addRequestInterceptor(
+ final HttpRequestInterceptor itcp, final int index) {
+ if (itcp == null) {
+ return;
+ }
+ this.requestInterceptors.add(index, itcp);
+ }
+
+ public void addResponseInterceptor(
+ final HttpResponseInterceptor itcp, final int index) {
+ if (itcp == null) {
+ return;
+ }
+ this.responseInterceptors.add(index, itcp);
+ }
+
+ public void removeRequestInterceptorByClass(final Class<? extends HttpRequestInterceptor> clazz) {
+ for (final Iterator<HttpRequestInterceptor> it = this.requestInterceptors.iterator();
+ it.hasNext(); ) {
+ final Object request = it.next();
+ if (request.getClass().equals(clazz)) {
+ it.remove();
+ }
+ }
+ }
+
+ public void removeResponseInterceptorByClass(final Class<? extends HttpResponseInterceptor> clazz) {
+ for (final Iterator<HttpResponseInterceptor> it = this.responseInterceptors.iterator();
+ it.hasNext(); ) {
+ final Object request = it.next();
+ if (request.getClass().equals(clazz)) {
+ it.remove();
+ }
+ }
+ }
+
+ public final void addInterceptor(final HttpRequestInterceptor interceptor) {
+ addRequestInterceptor(interceptor);
+ }
+
+ public final void addInterceptor(final HttpRequestInterceptor interceptor, final int index) {
+ addRequestInterceptor(interceptor, index);
+ }
+
+ public int getRequestInterceptorCount() {
+ return this.requestInterceptors.size();
+ }
+
+ public HttpRequestInterceptor getRequestInterceptor(final int index) {
+ if ((index < 0) || (index >= this.requestInterceptors.size())) {
+ return null;
+ }
+ return this.requestInterceptors.get(index);
+ }
+
+ public void clearRequestInterceptors() {
+ this.requestInterceptors.clear();
+ }
+
+ public void addResponseInterceptor(final HttpResponseInterceptor itcp) {
+ if (itcp == null) {
+ return;
+ }
+ this.responseInterceptors.add(itcp);
+ }
+
+ public final void addInterceptor(final HttpResponseInterceptor interceptor) {
+ addResponseInterceptor(interceptor);
+ }
+
+ public final void addInterceptor(final HttpResponseInterceptor interceptor, final int index) {
+ addResponseInterceptor(interceptor, index);
+ }
+
+ public int getResponseInterceptorCount() {
+ return this.responseInterceptors.size();
+ }
+
+ public HttpResponseInterceptor getResponseInterceptor(final int index) {
+ if ((index < 0) || (index >= this.responseInterceptors.size())) {
+ return null;
+ }
+ return this.responseInterceptors.get(index);
+ }
+
+ public void clearResponseInterceptors() {
+ this.responseInterceptors.clear();
+ }
+
+ /**
+ * Sets the interceptor lists.
+ * First, both interceptor lists maintained by this processor
+ * will be cleared.
+ * Subsequently,
+ * elements of the argument list that are request interceptors will be
+ * added to the request interceptor list.
+ * Elements that are response interceptors will be
+ * added to the response interceptor list.
+ * Elements that are both request and response interceptor will be
+ * added to both lists.
+ * Elements that are neither request nor response interceptor
+ * will be ignored.
+ *
+ * @param list the list of request and response interceptors
+ * from which to initialize
+ */
+ public void setInterceptors(final List<?> list) {
+ Args.notNull(list, "Inteceptor list");
+ this.requestInterceptors.clear();
+ this.responseInterceptors.clear();
+ for (final Object obj : list) {
+ if (obj instanceof HttpRequestInterceptor) {
+ addInterceptor((HttpRequestInterceptor) obj);
+ }
+ if (obj instanceof HttpResponseInterceptor) {
+ addInterceptor((HttpResponseInterceptor) obj);
+ }
+ }
+ }
+
+ /**
+ * Clears both interceptor lists maintained by this processor.
+ */
+ public void clearInterceptors() {
+ clearRequestInterceptors();
+ clearResponseInterceptors();
+ }
+
+ public void process(
+ final HttpRequest request,
+ final HttpContext context)
+ throws IOException, HttpException {
+ for (final HttpRequestInterceptor interceptor : this.requestInterceptors) {
+ interceptor.process(request, context);
+ }
+ }
+
+ public void process(
+ final HttpResponse response,
+ final HttpContext context)
+ throws IOException, HttpException {
+ for (final HttpResponseInterceptor interceptor : this.responseInterceptors) {
+ interceptor.process(response, context);
+ }
+ }
+
+ /**
+ * Sets up the target to have the same list of interceptors
+ * as the current instance.
+ *
+ * @param target object to be initialised
+ */
+ protected void copyInterceptors(final BasicHttpProcessor target) {
+ target.requestInterceptors.clear();
+ target.requestInterceptors.addAll(this.requestInterceptors);
+ target.responseInterceptors.clear();
+ target.responseInterceptors.addAll(this.responseInterceptors);
+ }
+
+ /**
+ * Creates a copy of this instance
+ *
+ * @return new instance of the BasicHttpProcessor
+ */
+ public BasicHttpProcessor copy() {
+ final BasicHttpProcessor clone = new BasicHttpProcessor();
+ copyInterceptors(clone);
+ return clone;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ final BasicHttpProcessor clone = (BasicHttpProcessor) super.clone();
+ copyInterceptors(clone);
+ return clone;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ChainBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ChainBuilder.java
new file mode 100644
index 000000000..19971ffa1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ChainBuilder.java
@@ -0,0 +1,126 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * Builder class to build a linked list (chain) of unique class instances. Each class can have
+ * only one instance in the list. Useful for building lists of protocol interceptors.
+ *
+ * @see ImmutableHttpProcessor
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+final class ChainBuilder<E> {
+
+ private final LinkedList<E> list;
+ private final Map<Class<?>, E> uniqueClasses;
+
+ public ChainBuilder() {
+ this.list = new LinkedList<E>();
+ this.uniqueClasses = new HashMap<Class<?>, E>();
+ }
+
+ private void ensureUnique(final E e) {
+ final E previous = this.uniqueClasses.remove(e.getClass());
+ if (previous != null) {
+ this.list.remove(previous);
+ }
+ this.uniqueClasses.put(e.getClass(), e);
+ }
+
+ public ChainBuilder<E> addFirst(final E e) {
+ if (e == null) {
+ return this;
+ }
+ ensureUnique(e);
+ this.list.addFirst(e);
+ return this;
+ }
+
+ public ChainBuilder<E> addLast(final E e) {
+ if (e == null) {
+ return this;
+ }
+ ensureUnique(e);
+ this.list.addLast(e);
+ return this;
+ }
+
+ public ChainBuilder<E> addAllFirst(final Collection<E> c) {
+ if (c == null) {
+ return this;
+ }
+ for (final E e: c) {
+ addFirst(e);
+ }
+ return this;
+ }
+
+ public ChainBuilder<E> addAllFirst(final E... c) {
+ if (c == null) {
+ return this;
+ }
+ for (final E e: c) {
+ addFirst(e);
+ }
+ return this;
+ }
+
+ public ChainBuilder<E> addAllLast(final Collection<E> c) {
+ if (c == null) {
+ return this;
+ }
+ for (final E e: c) {
+ addLast(e);
+ }
+ return this;
+ }
+
+ public ChainBuilder<E> addAllLast(final E... c) {
+ if (c == null) {
+ return this;
+ }
+ for (final E e: c) {
+ addLast(e);
+ }
+ return this;
+ }
+
+ public LinkedList<E> build() {
+ return new LinkedList<E>(this.list);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/DefaultedHttpContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/DefaultedHttpContext.java
new file mode 100644
index 000000000..63ef87b98
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/DefaultedHttpContext.java
@@ -0,0 +1,84 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * {@link HttpContext} implementation that delegates resolution of an attribute
+ * to the given default {@link HttpContext} instance if the attribute is not
+ * present in the local one. The state of the local context can be mutated,
+ * whereas the default context is treated as read-only.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) no longer used.
+ */
+@Deprecated
+public final class DefaultedHttpContext implements HttpContext {
+
+ private final HttpContext local;
+ private final HttpContext defaults;
+
+ public DefaultedHttpContext(final HttpContext local, final HttpContext defaults) {
+ super();
+ this.local = Args.notNull(local, "HTTP context");
+ this.defaults = defaults;
+ }
+
+ public Object getAttribute(final String id) {
+ final Object obj = this.local.getAttribute(id);
+ if (obj == null) {
+ return this.defaults.getAttribute(id);
+ } else {
+ return obj;
+ }
+ }
+
+ public Object removeAttribute(final String id) {
+ return this.local.removeAttribute(id);
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ this.local.setAttribute(id, obj);
+ }
+
+ public HttpContext getDefaults() {
+ return this.defaults;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("[local: ").append(this.local);
+ buf.append("defaults: ").append(this.defaults);
+ buf.append("]");
+ return buf.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ExecutionContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ExecutionContext.java
new file mode 100644
index 000000000..b27a481df
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ExecutionContext.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+/**
+ * {@link HttpContext} attribute names for protocol execution.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3) use {@link HttpCoreContext}.
+ */
+@Deprecated
+public interface ExecutionContext {
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpConnection} object that
+ * represents the actual HTTP connection.
+ */
+ public static final String HTTP_CONNECTION = "http.connection";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpRequest} object that
+ * represents the actual HTTP request.
+ */
+ public static final String HTTP_REQUEST = "http.request";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpResponse} object that
+ * represents the actual HTTP response.
+ */
+ public static final String HTTP_RESPONSE = "http.response";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpHost} object that
+ * represents the connection target.
+ */
+ public static final String HTTP_TARGET_HOST = "http.target_host";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpHost} object that
+ * represents the connection proxy.
+ *
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public static final String HTTP_PROXY_HOST = "http.proxy_host";
+
+ /**
+ * Attribute name of a {@link Boolean} object that represents the
+ * the flag indicating whether the actual request has been fully transmitted
+ * to the target host.
+ */
+ public static final String HTTP_REQ_SENT = "http.request_sent";
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HTTP.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HTTP.java
new file mode 100644
index 000000000..593b3bfdf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HTTP.java
@@ -0,0 +1,135 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.nio.charset.Charset;
+
+import ch.boye.httpclientandroidlib.Consts;
+
+/**
+ * Constants and static helpers related to the HTTP protocol.
+ *
+ * @since 4.0
+ */
+public final class HTTP {
+
+ public static final int CR = 13; // <US-ASCII CR, carriage return (13)>
+ public static final int LF = 10; // <US-ASCII LF, linefeed (10)>
+ public static final int SP = 32; // <US-ASCII SP, space (32)>
+ public static final int HT = 9; // <US-ASCII HT, horizontal-tab (9)>
+
+ /** HTTP header definitions */
+ public static final String TRANSFER_ENCODING = "Transfer-Encoding";
+ public static final String CONTENT_LEN = "Content-Length";
+ public static final String CONTENT_TYPE = "Content-Type";
+ public static final String CONTENT_ENCODING = "Content-Encoding";
+ public static final String EXPECT_DIRECTIVE = "Expect";
+ public static final String CONN_DIRECTIVE = "Connection";
+ public static final String TARGET_HOST = "Host";
+ public static final String USER_AGENT = "User-Agent";
+ public static final String DATE_HEADER = "Date";
+ public static final String SERVER_HEADER = "Server";
+
+ /** HTTP expectations */
+ public static final String EXPECT_CONTINUE = "100-continue";
+
+ /** HTTP connection control */
+ public static final String CONN_CLOSE = "Close";
+ public static final String CONN_KEEP_ALIVE = "Keep-Alive";
+
+ /** Transfer encoding definitions */
+ public static final String CHUNK_CODING = "chunked";
+ public static final String IDENTITY_CODING = "identity";
+
+ public static final Charset DEF_CONTENT_CHARSET = Consts.ISO_8859_1;
+ public static final Charset DEF_PROTOCOL_CHARSET = Consts.ASCII;
+
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public static final String UTF_8 = "UTF-8";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public static final String UTF_16 = "UTF-16";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public static final String US_ASCII = "US-ASCII";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public static final String ASCII = "ASCII";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public static final String ISO_8859_1 = "ISO-8859-1";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public static final String DEFAULT_CONTENT_CHARSET = ISO_8859_1;
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public static final String DEFAULT_PROTOCOL_CHARSET = US_ASCII;
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public final static String OCTET_STREAM_TYPE = "application/octet-stream";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public final static String PLAIN_TEXT_TYPE = "text/plain";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public final static String CHARSET_PARAM = "; charset=";
+ /**
+ * @deprecated (4.2)
+ */
+ @Deprecated
+ public final static String DEFAULT_CONTENT_TYPE = OCTET_STREAM_TYPE;
+
+ public static boolean isWhitespace(final char ch) {
+ return ch == SP || ch == HT || ch == CR || ch == LF;
+ }
+
+ private HTTP() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpContext.java
new file mode 100644
index 000000000..c2b70ccea
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpContext.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+/**
+ * HttpContext represents execution state of an HTTP process. It is a structure
+ * that can be used to map an attribute name to an attribute value.
+ * <p/>
+ * The primary purpose of the HTTP context is to facilitate information sharing
+ * among various logically related components. HTTP context can be used
+ * to store a processing state for one message or several consecutive messages.
+ * Multiple logically related messages can participate in a logical session
+ * if the same context is reused between consecutive messages.
+ * <p>/
+ * IMPORTANT: Please note HTTP context implementation, even when thread safe,
+ * may not be used concurrently by multiple threads, as the context may contain
+ * thread unsafe attributes.
+ *
+ * @since 4.0
+ */
+public interface HttpContext {
+
+ /** The prefix reserved for use by HTTP components. "http." */
+ public static final String RESERVED_PREFIX = "http.";
+
+ /**
+ * Obtains attribute with the given name.
+ *
+ * @param id the attribute name.
+ * @return attribute value, or <code>null</code> if not set.
+ */
+ Object getAttribute(String id);
+
+ /**
+ * Sets value of the attribute with the given name.
+ *
+ * @param id the attribute name.
+ * @param obj the attribute value.
+ */
+ void setAttribute(String id, Object obj);
+
+ /**
+ * Removes attribute with the given name from the context.
+ *
+ * @param id the attribute name.
+ * @return attribute value, or <code>null</code> if not set.
+ */
+ Object removeAttribute(String id);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpCoreContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpCoreContext.java
new file mode 100644
index 000000000..3d4262751
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpCoreContext.java
@@ -0,0 +1,152 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import ch.boye.httpclientandroidlib.HttpConnection;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Implementation of {@link HttpContext} that provides convenience
+ * setters for user assignable attributes and getter for readable attributes.
+ *
+ * @since 4.3
+ */
+@NotThreadSafe
+public class HttpCoreContext implements HttpContext {
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpConnection} object that
+ * represents the actual HTTP connection.
+ */
+ public static final String HTTP_CONNECTION = "http.connection";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpRequest} object that
+ * represents the actual HTTP request.
+ */
+ public static final String HTTP_REQUEST = "http.request";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpResponse} object that
+ * represents the actual HTTP response.
+ */
+ public static final String HTTP_RESPONSE = "http.response";
+
+ /**
+ * Attribute name of a {@link ch.boye.httpclientandroidlib.HttpHost} object that
+ * represents the connection target.
+ */
+ public static final String HTTP_TARGET_HOST = "http.target_host";
+
+ /**
+ * Attribute name of a {@link Boolean} object that represents the
+ * the flag indicating whether the actual request has been fully transmitted
+ * to the target host.
+ */
+ public static final String HTTP_REQ_SENT = "http.request_sent";
+
+ public static HttpCoreContext create() {
+ return new HttpCoreContext(new BasicHttpContext());
+ }
+
+ public static HttpCoreContext adapt(final HttpContext context) {
+ Args.notNull(context, "HTTP context");
+ if (context instanceof HttpCoreContext) {
+ return (HttpCoreContext) context;
+ } else {
+ return new HttpCoreContext(context);
+ }
+ }
+
+ private final HttpContext context;
+
+ public HttpCoreContext(final HttpContext context) {
+ super();
+ this.context = context;
+ }
+
+ public HttpCoreContext() {
+ super();
+ this.context = new BasicHttpContext();
+ }
+
+ public Object getAttribute(final String id) {
+ return context.getAttribute(id);
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ context.setAttribute(id, obj);
+ }
+
+ public Object removeAttribute(final String id) {
+ return context.removeAttribute(id);
+ }
+
+ public <T> T getAttribute(final String attribname, final Class<T> clazz) {
+ Args.notNull(clazz, "Attribute class");
+ final Object obj = getAttribute(attribname);
+ if (obj == null) {
+ return null;
+ }
+ return clazz.cast(obj);
+ }
+
+ public <T extends HttpConnection> T getConnection(final Class<T> clazz) {
+ return getAttribute(HTTP_CONNECTION, clazz);
+ }
+
+ public HttpConnection getConnection() {
+ return getAttribute(HTTP_CONNECTION, HttpConnection.class);
+ }
+
+ public HttpRequest getRequest() {
+ return getAttribute(HTTP_REQUEST, HttpRequest.class);
+ }
+
+ public boolean isRequestSent() {
+ final Boolean b = getAttribute(HTTP_REQ_SENT, Boolean.class);
+ return b != null && b.booleanValue();
+ }
+
+ public HttpResponse getResponse() {
+ return getAttribute(HTTP_RESPONSE, HttpResponse.class);
+ }
+
+ public void setTargetHost(final HttpHost host) {
+ setAttribute(HTTP_TARGET_HOST, host);
+ }
+
+ public HttpHost getTargetHost() {
+ return getAttribute(HTTP_TARGET_HOST, HttpHost.class);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpDateGenerator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpDateGenerator.java
new file mode 100644
index 000000000..8e99c1ea2
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpDateGenerator.java
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+/**
+ * Generates a date in the format required by the HTTP protocol.
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class HttpDateGenerator {
+
+ /** Date format pattern used to generate the header in RFC 1123 format. */
+ public static final
+ String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
+
+ /** The time zone to use in the date header. */
+ public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
+ @GuardedBy("this")
+ private final DateFormat dateformat;
+ @GuardedBy("this")
+ private long dateAsLong = 0L;
+ @GuardedBy("this")
+ private String dateAsText = null;
+
+ public HttpDateGenerator() {
+ super();
+ this.dateformat = new SimpleDateFormat(PATTERN_RFC1123, Locale.US);
+ this.dateformat.setTimeZone(GMT);
+ }
+
+ public synchronized String getCurrentDate() {
+ final long now = System.currentTimeMillis();
+ if (now - this.dateAsLong > 1000) {
+ // Generate new date string
+ this.dateAsText = this.dateformat.format(new Date(now));
+ this.dateAsLong = now;
+ }
+ return this.dateAsText;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpExpectationVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpExpectationVerifier.java
new file mode 100644
index 000000000..105704616
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpExpectationVerifier.java
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+/**
+ * Defines an interface to verify whether an incoming HTTP request meets
+ * the target server's expectations.
+ *<p>
+ * The Expect request-header field is used to indicate that particular
+ * server behaviors are required by the client.
+ *</p>
+ *<pre>
+ * Expect = "Expect" ":" 1#expectation
+ *
+ * expectation = "100-continue" | expectation-extension
+ * expectation-extension = token [ "=" ( token | quoted-string )
+ * *expect-params ]
+ * expect-params = ";" token [ "=" ( token | quoted-string ) ]
+ *</pre>
+ *<p>
+ * A server that does not understand or is unable to comply with any of
+ * the expectation values in the Expect field of a request MUST respond
+ * with appropriate error status. The server MUST respond with a 417
+ * (Expectation Failed) status if any of the expectations cannot be met
+ * or, if there are other problems with the request, some other 4xx
+ * status.
+ *</p>
+ *
+ * @since 4.0
+ */
+public interface HttpExpectationVerifier {
+
+ /**
+ * Verifies whether the given request meets the server's expectations.
+ * <p>
+ * If the request fails to meet particular criteria, this method can
+ * trigger a terminal response back to the client by setting the status
+ * code of the response object to a value greater or equal to
+ * <code>200</code>. In this case the client will not have to transmit
+ * the request body. If the request meets expectations this method can
+ * terminate without modifying the response object. Per default the status
+ * code of the response object will be set to <code>100</code>.
+ *
+ * @param request the HTTP request.
+ * @param response the HTTP response.
+ * @param context the HTTP context.
+ * @throws HttpException in case of an HTTP protocol violation.
+ */
+ void verify(HttpRequest request, HttpResponse response, HttpContext context)
+ throws HttpException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessor.java
new file mode 100644
index 000000000..e4dac6795
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessor.java
@@ -0,0 +1,55 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+
+/**
+ * HTTP protocol processor is a collection of protocol interceptors that
+ * implements the 'Chain of Responsibility' pattern, where each individual
+ * protocol interceptor is expected to work on a particular aspect of the HTTP
+ * protocol the interceptor is responsible for.
+ * <p>
+ * Usually the order in which interceptors are executed should not matter as
+ * long as they do not depend on a particular state of the execution context.
+ * If protocol interceptors have interdependencies and therefore must be
+ * executed in a particular order, they should be added to the protocol
+ * processor in the same sequence as their expected execution order.
+ * <p>
+ * Protocol interceptors must be implemented as thread-safe. Similarly to
+ * servlets, protocol interceptors should not use instance variables unless
+ * access to those variables is synchronized.
+ *
+ * @since 4.0
+ */
+public interface HttpProcessor
+ extends HttpRequestInterceptor, HttpResponseInterceptor {
+
+ // no additional methods
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessorBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessorBuilder.java
new file mode 100644
index 000000000..29dfccd60
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpProcessorBuilder.java
@@ -0,0 +1,151 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+
+/**
+ * Builder for {@link HttpProcessor} instances.
+ *
+ * @since 4.3
+ */
+public class HttpProcessorBuilder {
+
+ private ChainBuilder<HttpRequestInterceptor> requestChainBuilder;
+ private ChainBuilder<HttpResponseInterceptor> responseChainBuilder;
+
+ public static HttpProcessorBuilder create() {
+ return new HttpProcessorBuilder();
+ }
+
+ HttpProcessorBuilder() {
+ super();
+ }
+
+ private ChainBuilder<HttpRequestInterceptor> getRequestChainBuilder() {
+ if (requestChainBuilder == null) {
+ requestChainBuilder = new ChainBuilder<HttpRequestInterceptor>();
+ }
+ return requestChainBuilder;
+ }
+
+ private ChainBuilder<HttpResponseInterceptor> getResponseChainBuilder() {
+ if (responseChainBuilder == null) {
+ responseChainBuilder = new ChainBuilder<HttpResponseInterceptor>();
+ }
+ return responseChainBuilder;
+ }
+
+ public HttpProcessorBuilder addFirst(final HttpRequestInterceptor e) {
+ if (e == null) {
+ return this;
+ }
+ getRequestChainBuilder().addFirst(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder addLast(final HttpRequestInterceptor e) {
+ if (e == null) {
+ return this;
+ }
+ getRequestChainBuilder().addLast(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder add(final HttpRequestInterceptor e) {
+ return addLast(e);
+ }
+
+ public HttpProcessorBuilder addAllFirst(final HttpRequestInterceptor... e) {
+ if (e == null) {
+ return this;
+ }
+ getRequestChainBuilder().addAllFirst(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder addAllLast(final HttpRequestInterceptor... e) {
+ if (e == null) {
+ return this;
+ }
+ getRequestChainBuilder().addAllLast(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder addAll(final HttpRequestInterceptor... e) {
+ return addAllLast(e);
+ }
+
+ public HttpProcessorBuilder addFirst(final HttpResponseInterceptor e) {
+ if (e == null) {
+ return this;
+ }
+ getResponseChainBuilder().addFirst(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder addLast(final HttpResponseInterceptor e) {
+ if (e == null) {
+ return this;
+ }
+ getResponseChainBuilder().addLast(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder add(final HttpResponseInterceptor e) {
+ return addLast(e);
+ }
+
+ public HttpProcessorBuilder addAllFirst(final HttpResponseInterceptor... e) {
+ if (e == null) {
+ return this;
+ }
+ getResponseChainBuilder().addAllFirst(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder addAllLast(final HttpResponseInterceptor... e) {
+ if (e == null) {
+ return this;
+ }
+ getResponseChainBuilder().addAllLast(e);
+ return this;
+ }
+
+ public HttpProcessorBuilder addAll(final HttpResponseInterceptor... e) {
+ return addAllLast(e);
+ }
+
+ public HttpProcessor build() {
+ return new ImmutableHttpProcessor(
+ requestChainBuilder != null ? requestChainBuilder.build() : null,
+ responseChainBuilder != null ? responseChainBuilder.build() : null);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestExecutor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestExecutor.java
new file mode 100644
index 000000000..d895f0420
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestExecutor.java
@@ -0,0 +1,311 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpClientConnection;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * <tt>HttpRequestExecutor</tt> is a client side HTTP protocol handler based
+ * on the blocking (classic) I/O model.
+ * <p/>
+ * <tt>HttpRequestExecutor</tt> relies on {@link HttpProcessor} to generate
+ * mandatory protocol headers for all outgoing messages and apply common,
+ * cross-cutting message transformations to all incoming and outgoing messages.
+ * Application specific processing can be implemented outside
+ * <tt>HttpRequestExecutor</tt> once the request has been executed and
+ * a response has been received.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class HttpRequestExecutor {
+
+ public static final int DEFAULT_WAIT_FOR_CONTINUE = 3000;
+
+ private final int waitForContinue;
+
+ /**
+ * Creates new instance of HttpRequestExecutor.
+ *
+ * @since 4.3
+ */
+ public HttpRequestExecutor(final int waitForContinue) {
+ super();
+ this.waitForContinue = Args.positive(waitForContinue, "Wait for continue time");
+ }
+
+ public HttpRequestExecutor() {
+ this(DEFAULT_WAIT_FOR_CONTINUE);
+ }
+
+ /**
+ * Decide whether a response comes with an entity.
+ * The implementation in this class is based on RFC 2616.
+ * <br/>
+ * Derived executors can override this method to handle
+ * methods and response codes not specified in RFC 2616.
+ *
+ * @param request the request, to obtain the executed method
+ * @param response the response, to obtain the status code
+ */
+ protected boolean canResponseHaveBody(final HttpRequest request,
+ final HttpResponse response) {
+
+ if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
+ return false;
+ }
+ final int status = response.getStatusLine().getStatusCode();
+ return status >= HttpStatus.SC_OK
+ && status != HttpStatus.SC_NO_CONTENT
+ && status != HttpStatus.SC_NOT_MODIFIED
+ && status != HttpStatus.SC_RESET_CONTENT;
+ }
+
+ /**
+ * Sends the request and obtain a response.
+ *
+ * @param request the request to execute.
+ * @param conn the connection over which to execute the request.
+ *
+ * @return the response to the request.
+ *
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ public HttpResponse execute(
+ final HttpRequest request,
+ final HttpClientConnection conn,
+ final HttpContext context) throws IOException, HttpException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(conn, "Client connection");
+ Args.notNull(context, "HTTP context");
+ try {
+ HttpResponse response = doSendRequest(request, conn, context);
+ if (response == null) {
+ response = doReceiveResponse(request, conn, context);
+ }
+ return response;
+ } catch (final IOException ex) {
+ closeConnection(conn);
+ throw ex;
+ } catch (final HttpException ex) {
+ closeConnection(conn);
+ throw ex;
+ } catch (final RuntimeException ex) {
+ closeConnection(conn);
+ throw ex;
+ }
+ }
+
+ private static void closeConnection(final HttpClientConnection conn) {
+ try {
+ conn.close();
+ } catch (final IOException ignore) {
+ }
+ }
+
+ /**
+ * Pre-process the given request using the given protocol processor and
+ * initiates the process of request execution.
+ *
+ * @param request the request to prepare
+ * @param processor the processor to use
+ * @param context the context for sending the request
+ *
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ public void preProcess(
+ final HttpRequest request,
+ final HttpProcessor processor,
+ final HttpContext context) throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(processor, "HTTP processor");
+ Args.notNull(context, "HTTP context");
+ context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+ processor.process(request, context);
+ }
+
+ /**
+ * Send the given request over the given connection.
+ * <p>
+ * This method also handles the expect-continue handshake if necessary.
+ * If it does not have to handle an expect-continue handshake, it will
+ * not use the connection for reading or anything else that depends on
+ * data coming in over the connection.
+ *
+ * @param request the request to send, already
+ * {@link #preProcess preprocessed}
+ * @param conn the connection over which to send the request,
+ * already established
+ * @param context the context for sending the request
+ *
+ * @return a terminal response received as part of an expect-continue
+ * handshake, or
+ * <code>null</code> if the expect-continue handshake is not used
+ *
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ protected HttpResponse doSendRequest(
+ final HttpRequest request,
+ final HttpClientConnection conn,
+ final HttpContext context) throws IOException, HttpException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(conn, "Client connection");
+ Args.notNull(context, "HTTP context");
+
+ HttpResponse response = null;
+
+ context.setAttribute(HttpCoreContext.HTTP_CONNECTION, conn);
+ context.setAttribute(HttpCoreContext.HTTP_REQ_SENT, Boolean.FALSE);
+
+ conn.sendRequestHeader(request);
+ if (request instanceof HttpEntityEnclosingRequest) {
+ // Check for expect-continue handshake. We have to flush the
+ // headers and wait for an 100-continue response to handle it.
+ // If we get a different response, we must not send the entity.
+ boolean sendentity = true;
+ final ProtocolVersion ver =
+ request.getRequestLine().getProtocolVersion();
+ if (((HttpEntityEnclosingRequest) request).expectContinue() &&
+ !ver.lessEquals(HttpVersion.HTTP_1_0)) {
+
+ conn.flush();
+ // As suggested by RFC 2616 section 8.2.3, we don't wait for a
+ // 100-continue response forever. On timeout, send the entity.
+ if (conn.isResponseAvailable(this.waitForContinue)) {
+ response = conn.receiveResponseHeader();
+ if (canResponseHaveBody(request, response)) {
+ conn.receiveResponseEntity(response);
+ }
+ final int status = response.getStatusLine().getStatusCode();
+ if (status < 200) {
+ if (status != HttpStatus.SC_CONTINUE) {
+ throw new ProtocolException(
+ "Unexpected response: " + response.getStatusLine());
+ }
+ // discard 100-continue
+ response = null;
+ } else {
+ sendentity = false;
+ }
+ }
+ }
+ if (sendentity) {
+ conn.sendRequestEntity((HttpEntityEnclosingRequest) request);
+ }
+ }
+ conn.flush();
+ context.setAttribute(HttpCoreContext.HTTP_REQ_SENT, Boolean.TRUE);
+ return response;
+ }
+
+ /**
+ * Waits for and receives a response.
+ * This method will automatically ignore intermediate responses
+ * with status code 1xx.
+ *
+ * @param request the request for which to obtain the response
+ * @param conn the connection over which the request was sent
+ * @param context the context for receiving the response
+ *
+ * @return the terminal response, not yet post-processed
+ *
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ protected HttpResponse doReceiveResponse(
+ final HttpRequest request,
+ final HttpClientConnection conn,
+ final HttpContext context) throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ Args.notNull(conn, "Client connection");
+ Args.notNull(context, "HTTP context");
+ HttpResponse response = null;
+ int statusCode = 0;
+
+ while (response == null || statusCode < HttpStatus.SC_OK) {
+
+ response = conn.receiveResponseHeader();
+ if (canResponseHaveBody(request, response)) {
+ conn.receiveResponseEntity(response);
+ }
+ statusCode = response.getStatusLine().getStatusCode();
+
+ } // while intermediate response
+
+ return response;
+ }
+
+ /**
+ * Post-processes the given response using the given protocol processor and
+ * completes the process of request execution.
+ * <p>
+ * This method does <i>not</i> read the response entity, if any.
+ * The connection over which content of the response entity is being
+ * streamed from cannot be reused until
+ * {@link ch.boye.httpclientandroidlib.util.EntityUtils#consume(ch.boye.httpclientandroidlib.HttpEntity)}
+ * has been invoked.
+ *
+ * @param response the response object to post-process
+ * @param processor the processor to use
+ * @param context the context for post-processing the response
+ *
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ public void postProcess(
+ final HttpResponse response,
+ final HttpProcessor processor,
+ final HttpContext context) throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ Args.notNull(processor, "HTTP processor");
+ Args.notNull(context, "HTTP context");
+ context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+ processor.process(response, context);
+ }
+
+} // class HttpRequestExecutor
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandler.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandler.java
new file mode 100644
index 000000000..b948ae65d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandler.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+/**
+ * HttpRequestHandler represents a routine for processing of a specific group
+ * of HTTP requests. Protocol handlers are designed to take care of protocol
+ * specific aspects, whereas individual request handlers are expected to take
+ * care of application specific HTTP processing. The main purpose of a request
+ * handler is to generate a response object with a content entity to be sent
+ * back to the client in response to the given request
+ *
+ * @since 4.0
+ */
+public interface HttpRequestHandler {
+
+ /**
+ * Handles the request and produces a response to be sent back to
+ * the client.
+ *
+ * @param request the HTTP request.
+ * @param response the HTTP response.
+ * @param context the HTTP execution context.
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ void handle(HttpRequest request, HttpResponse response, HttpContext context)
+ throws HttpException, IOException;
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerMapper.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerMapper.java
new file mode 100644
index 000000000..e97da4e88
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerMapper.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+
+/**
+ * HttpRequestHandlerMapper can be used to resolve an instance of
+ * {@link HttpRequestHandler} matching a particular {@link HttpRequest}. Usually the
+ * mapped request handler will be used to process the request.
+ *
+ * @since 4.3
+ */
+public interface HttpRequestHandlerMapper {
+
+ /**
+ * Looks up a handler matching the given request.
+ *
+ * @param request the request to map to a handler
+ * @return HTTP request handler or <code>null</code> if no match
+ * is found.
+ */
+ HttpRequestHandler lookup(HttpRequest request);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java
new file mode 100644
index 000000000..3592d00ac
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java
@@ -0,0 +1,107 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Maintains a map of HTTP request handlers keyed by a request URI pattern.
+ * <br>
+ * Patterns may have three formats:
+ * <ul>
+ * <li><code>*</code></li>
+ * <li><code>*&lt;uri&gt;</code></li>
+ * <li><code>&lt;uri&gt;*</code></li>
+ * </ul>
+ * <br>
+ * This class can be used to resolve an instance of
+ * {@link HttpRequestHandler} matching a particular request URI. Usually the
+ * resolved request handler will be used to process the request with the
+ * specified request URI.
+ *
+ * @since 4.0
+ * @deprecated (4.3) use {@link UriHttpRequestHandlerMapper}
+ */
+@ThreadSafe // provided injected dependencies are thread-safe
+@Deprecated
+public class HttpRequestHandlerRegistry implements HttpRequestHandlerResolver {
+
+ private final UriPatternMatcher<HttpRequestHandler> matcher;
+
+ public HttpRequestHandlerRegistry() {
+ matcher = new UriPatternMatcher<HttpRequestHandler>();
+ }
+
+ /**
+ * Registers the given {@link HttpRequestHandler} as a handler for URIs
+ * matching the given pattern.
+ *
+ * @param pattern the pattern to register the handler for.
+ * @param handler the handler.
+ */
+ public void register(final String pattern, final HttpRequestHandler handler) {
+ Args.notNull(pattern, "URI request pattern");
+ Args.notNull(handler, "Request handler");
+ matcher.register(pattern, handler);
+ }
+
+ /**
+ * Removes registered handler, if exists, for the given pattern.
+ *
+ * @param pattern the pattern to unregister the handler for.
+ */
+ public void unregister(final String pattern) {
+ matcher.unregister(pattern);
+ }
+
+ /**
+ * Sets handlers from the given map.
+ * @param map the map containing handlers keyed by their URI patterns.
+ */
+ public void setHandlers(final Map<String, HttpRequestHandler> map) {
+ matcher.setObjects(map);
+ }
+
+ /**
+ * Get the handler map.
+ * @return The map of handlers and their associated URI patterns.
+ *
+ * @since 4.2
+ */
+ public Map<String, HttpRequestHandler> getHandlers() {
+ return matcher.getObjects();
+ }
+
+ public HttpRequestHandler lookup(final String requestURI) {
+ return matcher.lookup(requestURI);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerResolver.java
new file mode 100644
index 000000000..a898b8d18
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestHandlerResolver.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+/**
+ * HttpRequestHandlerResolver can be used to resolve an instance of
+ * {@link HttpRequestHandler} matching a particular request URI. Usually the
+ * mapped request handler will be used to process the request with the
+ * specified request URI.
+ *
+ * @since 4.0
+ * @deprecated see {@link HttpRequestHandlerMapper}
+ */
+@Deprecated
+public interface HttpRequestHandlerResolver {
+
+ /**
+ * Looks up a handler matching the given request URI.
+ *
+ * @param requestURI the request URI
+ * @return HTTP request handler or <code>null</code> if no match
+ * is found.
+ */
+ HttpRequestHandler lookup(String requestURI);
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestInterceptorList.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestInterceptorList.java
new file mode 100644
index 000000000..da4fd6f86
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpRequestInterceptorList.java
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+
+/**
+ * Provides access to an ordered list of request interceptors.
+ * Lists are expected to be built upfront and used read-only afterwards
+ * for {@link HttpProcessor processing}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3)
+ */
+@Deprecated
+public interface HttpRequestInterceptorList {
+
+ /**
+ * Appends a request interceptor to this list.
+ *
+ * @param interceptor the request interceptor to add
+ */
+ void addRequestInterceptor(HttpRequestInterceptor interceptor);
+
+ /**
+ * Inserts a request interceptor at the specified index.
+ *
+ * @param interceptor the request interceptor to add
+ * @param index the index to insert the interceptor at
+ */
+ void addRequestInterceptor(HttpRequestInterceptor interceptor, int index);
+
+ /**
+ * Obtains the current size of this list.
+ *
+ * @return the number of request interceptors in this list
+ */
+ int getRequestInterceptorCount();
+
+ /**
+ * Obtains a request interceptor from this list.
+ *
+ * @param index the index of the interceptor to obtain,
+ * 0 for first
+ *
+ * @return the interceptor at the given index, or
+ * <code>null</code> if the index is out of range
+ */
+ HttpRequestInterceptor getRequestInterceptor(int index);
+
+ /**
+ * Removes all request interceptors from this list.
+ */
+ void clearRequestInterceptors();
+
+ /**
+ * Removes all request interceptor of the specified class
+ *
+ * @param clazz the class of the instances to be removed.
+ */
+ void removeRequestInterceptorByClass(Class<? extends HttpRequestInterceptor> clazz);
+
+ /**
+ * Sets the request interceptors in this list.
+ * This list will be cleared and re-initialized to contain
+ * all request interceptors from the argument list.
+ * If the argument list includes elements that are not request
+ * interceptors, the behavior is implementation dependent.
+ *
+ * @param list the list of request interceptors
+ */
+ void setInterceptors(List<?> list);
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpResponseInterceptorList.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpResponseInterceptorList.java
new file mode 100644
index 000000000..9265b6738
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpResponseInterceptorList.java
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+
+/**
+ * Provides access to an ordered list of response interceptors.
+ * Lists are expected to be built upfront and used read-only afterwards
+ * for {@link HttpProcessor processing}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.3)
+ */
+@Deprecated
+public interface HttpResponseInterceptorList {
+
+ /**
+ * Appends a response interceptor to this list.
+ *
+ * @param interceptor the response interceptor to add
+ */
+ void addResponseInterceptor(HttpResponseInterceptor interceptor);
+
+ /**
+ * Inserts a response interceptor at the specified index.
+ *
+ * @param interceptor the response interceptor to add
+ * @param index the index to insert the interceptor at
+ */
+ void addResponseInterceptor(HttpResponseInterceptor interceptor, int index);
+
+ /**
+ * Obtains the current size of this list.
+ *
+ * @return the number of response interceptors in this list
+ */
+ int getResponseInterceptorCount();
+
+ /**
+ * Obtains a response interceptor from this list.
+ *
+ * @param index the index of the interceptor to obtain,
+ * 0 for first
+ *
+ * @return the interceptor at the given index, or
+ * <code>null</code> if the index is out of range
+ */
+ HttpResponseInterceptor getResponseInterceptor(int index);
+
+ /**
+ * Removes all response interceptors from this list.
+ */
+ void clearResponseInterceptors();
+
+ /**
+ * Removes all response interceptor of the specified class
+ *
+ * @param clazz the class of the instances to be removed.
+ */
+ void removeResponseInterceptorByClass(Class<? extends HttpResponseInterceptor> clazz);
+
+ /**
+ * Sets the response interceptors in this list.
+ * This list will be cleared and re-initialized to contain
+ * all response interceptors from the argument list.
+ * If the argument list includes elements that are not response
+ * interceptors, the behavior is implementation dependent.
+ *
+ * @param list the list of response interceptors
+ */
+ void setInterceptors(List<?> list);
+
+}
+
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpService.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpService.java
new file mode 100644
index 000000000..13defa2d9
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpService.java
@@ -0,0 +1,447 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseFactory;
+import ch.boye.httpclientandroidlib.HttpServerConnection;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.MethodNotSupportedException;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.UnsupportedHttpVersionException;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.entity.ByteArrayEntity;
+import ch.boye.httpclientandroidlib.impl.DefaultConnectionReuseStrategy;
+import ch.boye.httpclientandroidlib.impl.DefaultHttpResponseFactory;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+import ch.boye.httpclientandroidlib.util.EncodingUtils;
+import ch.boye.httpclientandroidlib.util.EntityUtils;
+
+/**
+ * <tt>HttpService</tt> is a server side HTTP protocol handler based on
+ * the classic (blocking) I/O model.
+ * <p/>
+ * <tt>HttpService</tt> relies on {@link HttpProcessor} to generate mandatory
+ * protocol headers for all outgoing messages and apply common, cross-cutting
+ * message transformations to all incoming and outgoing messages, whereas
+ * individual {@link HttpRequestHandler}s are expected to implement
+ * application specific content generation and processing.
+ * <p/>
+ * <tt>HttpService</tt> uses {@link HttpRequestHandlerMapper} to map
+ * matching request handler for a particular request URI of an incoming HTTP
+ * request.
+ * <p/>
+ * <tt>HttpService</tt> can use optional {@link HttpExpectationVerifier}
+ * to ensure that incoming requests meet server's expectations.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@Immutable // provided injected dependencies are immutable and deprecated methods are not used
+public class HttpService {
+
+ /**
+ * TODO: make all variables final in the next major version
+ */
+ private volatile HttpParams params = null;
+ private volatile HttpProcessor processor = null;
+ private volatile HttpRequestHandlerMapper handlerMapper = null;
+ private volatile ConnectionReuseStrategy connStrategy = null;
+ private volatile HttpResponseFactory responseFactory = null;
+ private volatile HttpExpectationVerifier expectationVerifier = null;
+
+ /**
+ * Create a new HTTP service.
+ *
+ * @param processor the processor to use on requests and responses
+ * @param connStrategy the connection reuse strategy
+ * @param responseFactory the response factory
+ * @param handlerResolver the handler resolver. May be null.
+ * @param expectationVerifier the expectation verifier. May be null.
+ * @param params the HTTP parameters
+ *
+ * @since 4.1
+ * @deprecated (4.3) use {@link HttpService#HttpService(HttpProcessor, ConnectionReuseStrategy,
+ * HttpResponseFactory, HttpRequestHandlerMapper, HttpExpectationVerifier)}
+ */
+ @Deprecated
+ public HttpService(
+ final HttpProcessor processor,
+ final ConnectionReuseStrategy connStrategy,
+ final HttpResponseFactory responseFactory,
+ final HttpRequestHandlerResolver handlerResolver,
+ final HttpExpectationVerifier expectationVerifier,
+ final HttpParams params) {
+ this(processor,
+ connStrategy,
+ responseFactory,
+ new HttpRequestHandlerResolverAdapter(handlerResolver),
+ expectationVerifier);
+ this.params = params;
+ }
+
+ /**
+ * Create a new HTTP service.
+ *
+ * @param processor the processor to use on requests and responses
+ * @param connStrategy the connection reuse strategy
+ * @param responseFactory the response factory
+ * @param handlerResolver the handler resolver. May be null.
+ * @param params the HTTP parameters
+ *
+ * @since 4.1
+ * @deprecated (4.3) use {@link HttpService#HttpService(HttpProcessor, ConnectionReuseStrategy,
+ * HttpResponseFactory, HttpRequestHandlerMapper)}
+ */
+ @Deprecated
+ public HttpService(
+ final HttpProcessor processor,
+ final ConnectionReuseStrategy connStrategy,
+ final HttpResponseFactory responseFactory,
+ final HttpRequestHandlerResolver handlerResolver,
+ final HttpParams params) {
+ this(processor,
+ connStrategy,
+ responseFactory,
+ new HttpRequestHandlerResolverAdapter(handlerResolver),
+ null);
+ this.params = params;
+ }
+
+ /**
+ * Create a new HTTP service.
+ *
+ * @param proc the processor to use on requests and responses
+ * @param connStrategy the connection reuse strategy
+ * @param responseFactory the response factory
+ *
+ * @deprecated (4.1) use {@link HttpService#HttpService(HttpProcessor,
+ * ConnectionReuseStrategy, HttpResponseFactory, HttpRequestHandlerResolver, HttpParams)}
+ */
+ @Deprecated
+ public HttpService(
+ final HttpProcessor proc,
+ final ConnectionReuseStrategy connStrategy,
+ final HttpResponseFactory responseFactory) {
+ super();
+ setHttpProcessor(proc);
+ setConnReuseStrategy(connStrategy);
+ setResponseFactory(responseFactory);
+ }
+
+ /**
+ * Create a new HTTP service.
+ *
+ * @param processor the processor to use on requests and responses
+ * @param connStrategy the connection reuse strategy. If <code>null</code>
+ * {@link DefaultConnectionReuseStrategy#INSTANCE} will be used.
+ * @param responseFactory the response factory. If <code>null</code>
+ * {@link DefaultHttpResponseFactory#INSTANCE} will be used.
+ * @param handlerMapper the handler mapper. May be null.
+ * @param expectationVerifier the expectation verifier. May be null.
+ *
+ * @since 4.3
+ */
+ public HttpService(
+ final HttpProcessor processor,
+ final ConnectionReuseStrategy connStrategy,
+ final HttpResponseFactory responseFactory,
+ final HttpRequestHandlerMapper handlerMapper,
+ final HttpExpectationVerifier expectationVerifier) {
+ super();
+ this.processor = Args.notNull(processor, "HTTP processor");
+ this.connStrategy = connStrategy != null ? connStrategy :
+ DefaultConnectionReuseStrategy.INSTANCE;
+ this.responseFactory = responseFactory != null ? responseFactory :
+ DefaultHttpResponseFactory.INSTANCE;
+ this.handlerMapper = handlerMapper;
+ this.expectationVerifier = expectationVerifier;
+ }
+
+ /**
+ * Create a new HTTP service.
+ *
+ * @param processor the processor to use on requests and responses
+ * @param connStrategy the connection reuse strategy. If <code>null</code>
+ * {@link DefaultConnectionReuseStrategy#INSTANCE} will be used.
+ * @param responseFactory the response factory. If <code>null</code>
+ * {@link DefaultHttpResponseFactory#INSTANCE} will be used.
+ * @param handlerMapper the handler mapper. May be null.
+ *
+ * @since 4.3
+ */
+ public HttpService(
+ final HttpProcessor processor,
+ final ConnectionReuseStrategy connStrategy,
+ final HttpResponseFactory responseFactory,
+ final HttpRequestHandlerMapper handlerMapper) {
+ this(processor, connStrategy, responseFactory, handlerMapper, null);
+ }
+
+ /**
+ * Create a new HTTP service.
+ *
+ * @param processor the processor to use on requests and responses
+ * @param handlerMapper the handler mapper. May be null.
+ *
+ * @since 4.3
+ */
+ public HttpService(
+ final HttpProcessor processor, final HttpRequestHandlerMapper handlerMapper) {
+ this(processor, null, null, handlerMapper, null);
+ }
+
+ /**
+ * @deprecated (4.1) set {@link HttpProcessor} using constructor
+ */
+ @Deprecated
+ public void setHttpProcessor(final HttpProcessor processor) {
+ Args.notNull(processor, "HTTP processor");
+ this.processor = processor;
+ }
+
+ /**
+ * @deprecated (4.1) set {@link ConnectionReuseStrategy} using constructor
+ */
+ @Deprecated
+ public void setConnReuseStrategy(final ConnectionReuseStrategy connStrategy) {
+ Args.notNull(connStrategy, "Connection reuse strategy");
+ this.connStrategy = connStrategy;
+ }
+
+ /**
+ * @deprecated (4.1) set {@link HttpResponseFactory} using constructor
+ */
+ @Deprecated
+ public void setResponseFactory(final HttpResponseFactory responseFactory) {
+ Args.notNull(responseFactory, "Response factory");
+ this.responseFactory = responseFactory;
+ }
+
+ /**
+ * @deprecated (4.1) set {@link HttpResponseFactory} using constructor
+ */
+ @Deprecated
+ public void setParams(final HttpParams params) {
+ this.params = params;
+ }
+
+ /**
+ * @deprecated (4.1) set {@link HttpRequestHandlerResolver} using constructor
+ */
+ @Deprecated
+ public void setHandlerResolver(final HttpRequestHandlerResolver handlerResolver) {
+ this.handlerMapper = new HttpRequestHandlerResolverAdapter(handlerResolver);
+ }
+
+ /**
+ * @deprecated (4.1) set {@link HttpExpectationVerifier} using constructor
+ */
+ @Deprecated
+ public void setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
+ this.expectationVerifier = expectationVerifier;
+ }
+
+ /**
+ * @deprecated (4.3) no longer used.
+ */
+ @Deprecated
+ public HttpParams getParams() {
+ return this.params;
+ }
+
+ /**
+ * Handles receives one HTTP request over the given connection within the
+ * given execution context and sends a response back to the client.
+ *
+ * @param conn the active connection to the client
+ * @param context the actual execution context.
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ public void handleRequest(
+ final HttpServerConnection conn,
+ final HttpContext context) throws IOException, HttpException {
+
+ context.setAttribute(HttpCoreContext.HTTP_CONNECTION, conn);
+
+ HttpResponse response = null;
+
+ try {
+
+ final HttpRequest request = conn.receiveRequestHeader();
+ if (request instanceof HttpEntityEnclosingRequest) {
+
+ if (((HttpEntityEnclosingRequest) request).expectContinue()) {
+ response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_CONTINUE, context);
+ if (this.expectationVerifier != null) {
+ try {
+ this.expectationVerifier.verify(request, response, context);
+ } catch (final HttpException ex) {
+ response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0,
+ HttpStatus.SC_INTERNAL_SERVER_ERROR, context);
+ handleException(ex, response);
+ }
+ }
+ if (response.getStatusLine().getStatusCode() < 200) {
+ // Send 1xx response indicating the server expections
+ // have been met
+ conn.sendResponseHeader(response);
+ conn.flush();
+ response = null;
+ conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
+ }
+ } else {
+ conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
+ }
+ }
+
+ context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+
+ if (response == null) {
+ response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_OK, context);
+ this.processor.process(request, context);
+ doService(request, response, context);
+ }
+
+ // Make sure the request content is fully consumed
+ if (request instanceof HttpEntityEnclosingRequest) {
+ final HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
+ EntityUtils.consume(entity);
+ }
+
+ } catch (final HttpException ex) {
+ response = this.responseFactory.newHttpResponse
+ (HttpVersion.HTTP_1_0, HttpStatus.SC_INTERNAL_SERVER_ERROR,
+ context);
+ handleException(ex, response);
+ }
+
+ context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+
+ this.processor.process(response, context);
+ conn.sendResponseHeader(response);
+ conn.sendResponseEntity(response);
+ conn.flush();
+
+ if (!this.connStrategy.keepAlive(response, context)) {
+ conn.close();
+ }
+ }
+
+ /**
+ * Handles the given exception and generates an HTTP response to be sent
+ * back to the client to inform about the exceptional condition encountered
+ * in the course of the request processing.
+ *
+ * @param ex the exception.
+ * @param response the HTTP response.
+ */
+ protected void handleException(final HttpException ex, final HttpResponse response) {
+ if (ex instanceof MethodNotSupportedException) {
+ response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
+ } else if (ex instanceof UnsupportedHttpVersionException) {
+ response.setStatusCode(HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED);
+ } else if (ex instanceof ProtocolException) {
+ response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
+ } else {
+ response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+ }
+ String message = ex.getMessage();
+ if (message == null) {
+ message = ex.toString();
+ }
+ final byte[] msg = EncodingUtils.getAsciiBytes(message);
+ final ByteArrayEntity entity = new ByteArrayEntity(msg);
+ entity.setContentType("text/plain; charset=US-ASCII");
+ response.setEntity(entity);
+ }
+
+ /**
+ * The default implementation of this method attempts to resolve an
+ * {@link HttpRequestHandler} for the request URI of the given request
+ * and, if found, executes its
+ * {@link HttpRequestHandler#handle(HttpRequest, HttpResponse, HttpContext)}
+ * method.
+ * <p>
+ * Super-classes can override this method in order to provide a custom
+ * implementation of the request processing logic.
+ *
+ * @param request the HTTP request.
+ * @param response the HTTP response.
+ * @param context the execution context.
+ * @throws IOException in case of an I/O error.
+ * @throws HttpException in case of HTTP protocol violation or a processing
+ * problem.
+ */
+ protected void doService(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
+ HttpRequestHandler handler = null;
+ if (this.handlerMapper != null) {
+ handler = this.handlerMapper.lookup(request);
+ }
+ if (handler != null) {
+ handler.handle(request, response, context);
+ } else {
+ response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
+ }
+ }
+
+ /**
+ * Adaptor class to transition from HttpRequestHandlerResolver to HttpRequestHandlerMapper.
+ */
+ @Deprecated
+ private static class HttpRequestHandlerResolverAdapter implements HttpRequestHandlerMapper {
+
+ private final HttpRequestHandlerResolver resolver;
+
+ public HttpRequestHandlerResolverAdapter(final HttpRequestHandlerResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ public HttpRequestHandler lookup(final HttpRequest request) {
+ return resolver.lookup(request.getRequestLine().getUri());
+ }
+
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ImmutableHttpProcessor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ImmutableHttpProcessor.java
new file mode 100644
index 000000000..8cb80c91b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ImmutableHttpProcessor.java
@@ -0,0 +1,143 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+import java.util.List;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+
+/**
+ * Immutable {@link HttpProcessor}.
+ *
+ * @since 4.1
+ */
+@ThreadSafe // provided injected dependencies are immutable
+public final class ImmutableHttpProcessor implements HttpProcessor {
+
+ private final HttpRequestInterceptor[] requestInterceptors;
+ private final HttpResponseInterceptor[] responseInterceptors;
+
+ public ImmutableHttpProcessor(
+ final HttpRequestInterceptor[] requestInterceptors,
+ final HttpResponseInterceptor[] responseInterceptors) {
+ super();
+ if (requestInterceptors != null) {
+ final int l = requestInterceptors.length;
+ this.requestInterceptors = new HttpRequestInterceptor[l];
+ System.arraycopy(requestInterceptors, 0, this.requestInterceptors, 0, l);
+ } else {
+ this.requestInterceptors = new HttpRequestInterceptor[0];
+ }
+ if (responseInterceptors != null) {
+ final int l = responseInterceptors.length;
+ this.responseInterceptors = new HttpResponseInterceptor[l];
+ System.arraycopy(responseInterceptors, 0, this.responseInterceptors, 0, l);
+ } else {
+ this.responseInterceptors = new HttpResponseInterceptor[0];
+ }
+ }
+
+ /**
+ * @since 4.3
+ */
+ public ImmutableHttpProcessor(
+ final List<HttpRequestInterceptor> requestInterceptors,
+ final List<HttpResponseInterceptor> responseInterceptors) {
+ super();
+ if (requestInterceptors != null) {
+ final int l = requestInterceptors.size();
+ this.requestInterceptors = requestInterceptors.toArray(new HttpRequestInterceptor[l]);
+ } else {
+ this.requestInterceptors = new HttpRequestInterceptor[0];
+ }
+ if (responseInterceptors != null) {
+ final int l = responseInterceptors.size();
+ this.responseInterceptors = responseInterceptors.toArray(new HttpResponseInterceptor[l]);
+ } else {
+ this.responseInterceptors = new HttpResponseInterceptor[0];
+ }
+ }
+
+ /**
+ * @deprecated (4.3) do not use.
+ */
+ @Deprecated
+ public ImmutableHttpProcessor(
+ final HttpRequestInterceptorList requestInterceptors,
+ final HttpResponseInterceptorList responseInterceptors) {
+ super();
+ if (requestInterceptors != null) {
+ final int count = requestInterceptors.getRequestInterceptorCount();
+ this.requestInterceptors = new HttpRequestInterceptor[count];
+ for (int i = 0; i < count; i++) {
+ this.requestInterceptors[i] = requestInterceptors.getRequestInterceptor(i);
+ }
+ } else {
+ this.requestInterceptors = new HttpRequestInterceptor[0];
+ }
+ if (responseInterceptors != null) {
+ final int count = responseInterceptors.getResponseInterceptorCount();
+ this.responseInterceptors = new HttpResponseInterceptor[count];
+ for (int i = 0; i < count; i++) {
+ this.responseInterceptors[i] = responseInterceptors.getResponseInterceptor(i);
+ }
+ } else {
+ this.responseInterceptors = new HttpResponseInterceptor[0];
+ }
+ }
+
+ public ImmutableHttpProcessor(final HttpRequestInterceptor... requestInterceptors) {
+ this(requestInterceptors, null);
+ }
+
+ public ImmutableHttpProcessor(final HttpResponseInterceptor... responseInterceptors) {
+ this(null, responseInterceptors);
+ }
+
+ public void process(
+ final HttpRequest request,
+ final HttpContext context) throws IOException, HttpException {
+ for (final HttpRequestInterceptor requestInterceptor : this.requestInterceptors) {
+ requestInterceptor.process(request, context);
+ }
+ }
+
+ public void process(
+ final HttpResponse response,
+ final HttpContext context) throws IOException, HttpException {
+ for (final HttpResponseInterceptor responseInterceptor : this.responseInterceptors) {
+ responseInterceptor.process(response, context);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestConnControl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestConnControl.java
new file mode 100644
index 000000000..1db509599
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestConnControl.java
@@ -0,0 +1,69 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * RequestConnControl is responsible for adding <code>Connection</code> header
+ * to the outgoing requests, which is essential for managing persistence of
+ * <code>HTTP/1.0</code> connections. This interceptor is recommended for
+ * client side protocol processors.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RequestConnControl implements HttpRequestInterceptor {
+
+ public RequestConnControl() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase("CONNECT")) {
+ return;
+ }
+
+ if (!request.containsHeader(HTTP.CONN_DIRECTIVE)) {
+ // Default policy is to keep connection alive
+ // whenever possible
+ request.addHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestContent.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestContent.java
new file mode 100644
index 000000000..2f90ad6d8
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestContent.java
@@ -0,0 +1,127 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * RequestContent is the most important interceptor for outgoing requests.
+ * It is responsible for delimiting content length by adding
+ * <code>Content-Length</code> or <code>Transfer-Content</code> headers based
+ * on the properties of the enclosed entity and the protocol version.
+ * This interceptor is required for correct functioning of client side protocol
+ * processors.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RequestContent implements HttpRequestInterceptor {
+
+ private final boolean overwrite;
+
+ /**
+ * Default constructor. The <code>Content-Length</code> or <code>Transfer-Encoding</code>
+ * will cause the interceptor to throw {@link ProtocolException} if already present in the
+ * response message.
+ */
+ public RequestContent() {
+ this(false);
+ }
+
+ /**
+ * Constructor that can be used to fine-tune behavior of this interceptor.
+ *
+ * @param overwrite If set to <code>true</code> the <code>Content-Length</code> and
+ * <code>Transfer-Encoding</code> headers will be created or updated if already present.
+ * If set to <code>false</code> the <code>Content-Length</code> and
+ * <code>Transfer-Encoding</code> headers will cause the interceptor to throw
+ * {@link ProtocolException} if already present in the response message.
+ *
+ * @since 4.2
+ */
+ public RequestContent(final boolean overwrite) {
+ super();
+ this.overwrite = overwrite;
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ if (request instanceof HttpEntityEnclosingRequest) {
+ if (this.overwrite) {
+ request.removeHeaders(HTTP.TRANSFER_ENCODING);
+ request.removeHeaders(HTTP.CONTENT_LEN);
+ } else {
+ if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
+ throw new ProtocolException("Transfer-encoding header already present");
+ }
+ if (request.containsHeader(HTTP.CONTENT_LEN)) {
+ throw new ProtocolException("Content-Length header already present");
+ }
+ }
+ final ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
+ final HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
+ if (entity == null) {
+ request.addHeader(HTTP.CONTENT_LEN, "0");
+ return;
+ }
+ // Must specify a transfer encoding or a content length
+ if (entity.isChunked() || entity.getContentLength() < 0) {
+ if (ver.lessEquals(HttpVersion.HTTP_1_0)) {
+ throw new ProtocolException(
+ "Chunked transfer encoding not allowed for " + ver);
+ }
+ request.addHeader(HTTP.TRANSFER_ENCODING, HTTP.CHUNK_CODING);
+ } else {
+ request.addHeader(HTTP.CONTENT_LEN, Long.toString(entity.getContentLength()));
+ }
+ // Specify a content type if known
+ if (entity.getContentType() != null && !request.containsHeader(
+ HTTP.CONTENT_TYPE )) {
+ request.addHeader(entity.getContentType());
+ }
+ // Specify a content encoding if known
+ if (entity.getContentEncoding() != null && !request.containsHeader(
+ HTTP.CONTENT_ENCODING)) {
+ request.addHeader(entity.getContentEncoding());
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestDate.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestDate.java
new file mode 100644
index 000000000..a2a0fa8b6
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestDate.java
@@ -0,0 +1,65 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * RequestDate interceptor is responsible for adding <code>Date</code> header
+ * to the outgoing requests This interceptor is optional for client side
+ * protocol processors.
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class RequestDate implements HttpRequestInterceptor {
+
+ private static final HttpDateGenerator DATE_GENERATOR = new HttpDateGenerator();
+
+ public RequestDate() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ if ((request instanceof HttpEntityEnclosingRequest) &&
+ !request.containsHeader(HTTP.DATE_HEADER)) {
+ final String httpdate = DATE_GENERATOR.getCurrentDate();
+ request.setHeader(HTTP.DATE_HEADER, httpdate);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestExpectContinue.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestExpectContinue.java
new file mode 100644
index 000000000..16cb8cd1c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestExpectContinue.java
@@ -0,0 +1,93 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * RequestExpectContinue is responsible for enabling the 'expect-continue'
+ * handshake by adding <code>Expect</code> header. This interceptor is
+ * recommended for client side protocol processors.
+ *
+ * @since 4.0
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class RequestExpectContinue implements HttpRequestInterceptor {
+
+ private final boolean activeByDefault;
+
+ /**
+ * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.protocol.RequestExpectContinue#RequestExpectContinue(boolean)}
+ */
+ @Deprecated
+ public RequestExpectContinue() {
+ this(false);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public RequestExpectContinue(final boolean activeByDefault) {
+ super();
+ this.activeByDefault = activeByDefault;
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+
+ if (!request.containsHeader(HTTP.EXPECT_DIRECTIVE)) {
+ if (request instanceof HttpEntityEnclosingRequest) {
+ final ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
+ final HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
+ // Do not send the expect header if request body is known to be empty
+ if (entity != null
+ && entity.getContentLength() != 0 && !ver.lessEquals(HttpVersion.HTTP_1_0)) {
+ final boolean active = request.getParams().getBooleanParameter(
+ CoreProtocolPNames.USE_EXPECT_CONTINUE, this.activeByDefault);
+ if (active) {
+ request.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestTargetHost.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestTargetHost.java
new file mode 100644
index 000000000..531a8a235
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestTargetHost.java
@@ -0,0 +1,95 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+import java.net.InetAddress;
+
+import ch.boye.httpclientandroidlib.HttpConnection;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpHost;
+import ch.boye.httpclientandroidlib.HttpInetConnection;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * RequestTargetHost is responsible for adding <code>Host</code> header. This
+ * interceptor is required for client side protocol processors.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class RequestTargetHost implements HttpRequestInterceptor {
+
+ public RequestTargetHost() {
+ super();
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+
+ final HttpCoreContext corecontext = HttpCoreContext.adapt(context);
+
+ final ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
+ final String method = request.getRequestLine().getMethod();
+ if (method.equalsIgnoreCase("CONNECT") && ver.lessEquals(HttpVersion.HTTP_1_0)) {
+ return;
+ }
+
+ if (!request.containsHeader(HTTP.TARGET_HOST)) {
+ HttpHost targethost = corecontext.getTargetHost();
+ if (targethost == null) {
+ final HttpConnection conn = corecontext.getConnection();
+ if (conn instanceof HttpInetConnection) {
+ // Populate the context with a default HTTP host based on the
+ // inet address of the target host
+ final InetAddress address = ((HttpInetConnection) conn).getRemoteAddress();
+ final int port = ((HttpInetConnection) conn).getRemotePort();
+ if (address != null) {
+ targethost = new HttpHost(address.getHostName(), port);
+ }
+ }
+ if (targethost == null) {
+ if (ver.lessEquals(HttpVersion.HTTP_1_0)) {
+ return;
+ } else {
+ throw new ProtocolException("Target host missing");
+ }
+ }
+ }
+ request.addHeader(HTTP.TARGET_HOST, targethost.toHostString());
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestUserAgent.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestUserAgent.java
new file mode 100644
index 000000000..23f4a45a7
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/RequestUserAgent.java
@@ -0,0 +1,79 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpRequestInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
+import ch.boye.httpclientandroidlib.params.HttpParams;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * RequestUserAgent is responsible for adding <code>User-Agent</code> header.
+ * This interceptor is recommended for client side protocol processors.
+ *
+ * @since 4.0
+ */
+@SuppressWarnings("deprecation")
+@Immutable
+public class RequestUserAgent implements HttpRequestInterceptor {
+
+ private final String userAgent;
+
+ public RequestUserAgent(final String userAgent) {
+ super();
+ this.userAgent = userAgent;
+ }
+
+ public RequestUserAgent() {
+ this(null);
+ }
+
+ public void process(final HttpRequest request, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(request, "HTTP request");
+ if (!request.containsHeader(HTTP.USER_AGENT)) {
+ String s = null;
+ final HttpParams params = request.getParams();
+ if (params != null) {
+ s = (String) params.getParameter(CoreProtocolPNames.USER_AGENT);
+ }
+ if (s == null) {
+ s = this.userAgent;
+ }
+ if (s != null) {
+ request.addHeader(HTTP.USER_AGENT, s);
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseConnControl.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseConnControl.java
new file mode 100644
index 000000000..29014e32f
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseConnControl.java
@@ -0,0 +1,105 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.Header;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * ResponseConnControl is responsible for adding <code>Connection</code> header
+ * to the outgoing responses, which is essential for managing persistence of
+ * <code>HTTP/1.0</code> connections. This interceptor is recommended for
+ * server side protocol processors.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ResponseConnControl implements HttpResponseInterceptor {
+
+ public ResponseConnControl() {
+ super();
+ }
+
+ public void process(final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+
+ final HttpCoreContext corecontext = HttpCoreContext.adapt(context);
+
+ // Always drop connection after certain type of responses
+ final int status = response.getStatusLine().getStatusCode();
+ if (status == HttpStatus.SC_BAD_REQUEST ||
+ status == HttpStatus.SC_REQUEST_TIMEOUT ||
+ status == HttpStatus.SC_LENGTH_REQUIRED ||
+ status == HttpStatus.SC_REQUEST_TOO_LONG ||
+ status == HttpStatus.SC_REQUEST_URI_TOO_LONG ||
+ status == HttpStatus.SC_SERVICE_UNAVAILABLE ||
+ status == HttpStatus.SC_NOT_IMPLEMENTED) {
+ response.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
+ return;
+ }
+ final Header explicit = response.getFirstHeader(HTTP.CONN_DIRECTIVE);
+ if (explicit != null && HTTP.CONN_CLOSE.equalsIgnoreCase(explicit.getValue())) {
+ // Connection persistence explicitly disabled
+ return;
+ }
+ // Always drop connection for HTTP/1.0 responses and below
+ // if the content body cannot be correctly delimited
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ final ProtocolVersion ver = response.getStatusLine().getProtocolVersion();
+ if (entity.getContentLength() < 0 &&
+ (!entity.isChunked() || ver.lessEquals(HttpVersion.HTTP_1_0))) {
+ response.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
+ return;
+ }
+ }
+ // Drop connection if requested by the client or request was <= 1.0
+ final HttpRequest request = corecontext.getRequest();
+ if (request != null) {
+ final Header header = request.getFirstHeader(HTTP.CONN_DIRECTIVE);
+ if (header != null) {
+ response.setHeader(HTTP.CONN_DIRECTIVE, header.getValue());
+ } else if (request.getProtocolVersion().lessEquals(HttpVersion.HTTP_1_0)) {
+ response.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseContent.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseContent.java
new file mode 100644
index 000000000..e2dcf2eef
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseContent.java
@@ -0,0 +1,133 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.HttpVersion;
+import ch.boye.httpclientandroidlib.ProtocolException;
+import ch.boye.httpclientandroidlib.ProtocolVersion;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * ResponseContent is the most important interceptor for outgoing responses.
+ * It is responsible for delimiting content length by adding
+ * <code>Content-Length</code> or <code>Transfer-Content</code> headers based
+ * on the properties of the enclosed entity and the protocol version.
+ * This interceptor is required for correct functioning of server side protocol
+ * processors.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ResponseContent implements HttpResponseInterceptor {
+
+ private final boolean overwrite;
+
+ /**
+ * Default constructor. The <code>Content-Length</code> or <code>Transfer-Encoding</code>
+ * will cause the interceptor to throw {@link ProtocolException} if already present in the
+ * response message.
+ */
+ public ResponseContent() {
+ this(false);
+ }
+
+ /**
+ * Constructor that can be used to fine-tune behavior of this interceptor.
+ *
+ * @param overwrite If set to <code>true</code> the <code>Content-Length</code> and
+ * <code>Transfer-Encoding</code> headers will be created or updated if already present.
+ * If set to <code>false</code> the <code>Content-Length</code> and
+ * <code>Transfer-Encoding</code> headers will cause the interceptor to throw
+ * {@link ProtocolException} if already present in the response message.
+ *
+ * @since 4.2
+ */
+ public ResponseContent(final boolean overwrite) {
+ super();
+ this.overwrite = overwrite;
+ }
+
+ /**
+ * Processes the response (possibly updating or inserting) Content-Length and Transfer-Encoding headers.
+ * @param response The HttpResponse to modify.
+ * @param context Unused.
+ * @throws ProtocolException If either the Content-Length or Transfer-Encoding headers are found.
+ * @throws IllegalArgumentException If the response is null.
+ */
+ public void process(final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ if (this.overwrite) {
+ response.removeHeaders(HTTP.TRANSFER_ENCODING);
+ response.removeHeaders(HTTP.CONTENT_LEN);
+ } else {
+ if (response.containsHeader(HTTP.TRANSFER_ENCODING)) {
+ throw new ProtocolException("Transfer-encoding header already present");
+ }
+ if (response.containsHeader(HTTP.CONTENT_LEN)) {
+ throw new ProtocolException("Content-Length header already present");
+ }
+ }
+ final ProtocolVersion ver = response.getStatusLine().getProtocolVersion();
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ final long len = entity.getContentLength();
+ if (entity.isChunked() && !ver.lessEquals(HttpVersion.HTTP_1_0)) {
+ response.addHeader(HTTP.TRANSFER_ENCODING, HTTP.CHUNK_CODING);
+ } else if (len >= 0) {
+ response.addHeader(HTTP.CONTENT_LEN, Long.toString(entity.getContentLength()));
+ }
+ // Specify a content type if known
+ if (entity.getContentType() != null && !response.containsHeader(
+ HTTP.CONTENT_TYPE )) {
+ response.addHeader(entity.getContentType());
+ }
+ // Specify a content encoding if known
+ if (entity.getContentEncoding() != null && !response.containsHeader(
+ HTTP.CONTENT_ENCODING)) {
+ response.addHeader(entity.getContentEncoding());
+ }
+ } else {
+ final int status = response.getStatusLine().getStatusCode();
+ if (status != HttpStatus.SC_NO_CONTENT
+ && status != HttpStatus.SC_NOT_MODIFIED
+ && status != HttpStatus.SC_RESET_CONTENT) {
+ response.addHeader(HTTP.CONTENT_LEN, "0");
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseDate.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseDate.java
new file mode 100644
index 000000000..300ff761e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseDate.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.HttpStatus;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * ResponseDate is responsible for adding <code>Date<c/ode> header to the
+ * outgoing responses. This interceptor is recommended for server side protocol
+ * processors.
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class ResponseDate implements HttpResponseInterceptor {
+
+ private static final HttpDateGenerator DATE_GENERATOR = new HttpDateGenerator();
+
+ public ResponseDate() {
+ super();
+ }
+
+ public void process(final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ final int status = response.getStatusLine().getStatusCode();
+ if ((status >= HttpStatus.SC_OK) &&
+ !response.containsHeader(HTTP.DATE_HEADER)) {
+ final String httpdate = DATE_GENERATOR.getCurrentDate();
+ response.setHeader(HTTP.DATE_HEADER, httpdate);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseServer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseServer.java
new file mode 100644
index 000000000..f0672a006
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/ResponseServer.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.io.IOException;
+
+import ch.boye.httpclientandroidlib.HttpException;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.HttpResponseInterceptor;
+import ch.boye.httpclientandroidlib.annotation.Immutable;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * ResponseServer is responsible for adding <code>Server</code> header. This
+ * interceptor is recommended for server side protocol processors.
+ *
+ * @since 4.0
+ */
+@Immutable
+public class ResponseServer implements HttpResponseInterceptor {
+
+ private final String originServer;
+
+ /**
+ * @since 4.3
+ */
+ public ResponseServer(final String originServer) {
+ super();
+ this.originServer = originServer;
+ }
+
+ public ResponseServer() {
+ this(null);
+ }
+
+ public void process(final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ Args.notNull(response, "HTTP response");
+ if (!response.containsHeader(HTTP.SERVER_HEADER)) {
+ if (this.originServer != null) {
+ response.addHeader(HTTP.SERVER_HEADER, this.originServer);
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/SyncBasicHttpContext.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/SyncBasicHttpContext.java
new file mode 100644
index 000000000..60138764b
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/SyncBasicHttpContext.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+/**
+ * Thread-safe extension of the {@link BasicHttpContext}.
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) HttpContext instances may not be shared by multiple threads
+ */
+@Deprecated
+public class SyncBasicHttpContext extends BasicHttpContext {
+
+ public SyncBasicHttpContext(final HttpContext parentContext) {
+ super(parentContext);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public SyncBasicHttpContext() {
+ super();
+ }
+
+ @Override
+ public synchronized Object getAttribute(final String id) {
+ return super.getAttribute(id);
+ }
+
+ @Override
+ public synchronized void setAttribute(final String id, final Object obj) {
+ super.setAttribute(id, obj);
+ }
+
+ @Override
+ public synchronized Object removeAttribute(final String id) {
+ return super.removeAttribute(id);
+ }
+
+ /**
+ * @since 4.2
+ */
+ @Override
+ public synchronized void clear() {
+ super.clear();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriHttpRequestHandlerMapper.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriHttpRequestHandlerMapper.java
new file mode 100644
index 000000000..f09dea611
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriHttpRequestHandlerMapper.java
@@ -0,0 +1,115 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import ch.boye.httpclientandroidlib.HttpRequest;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Maintains a map of HTTP request handlers keyed by a request URI pattern.
+ * <br>
+ * Patterns may have three formats:
+ * <ul>
+ * <li><code>*</code></li>
+ * <li><code>*&lt;uri&gt;</code></li>
+ * <li><code>&lt;uri&gt;*</code></li>
+ * </ul>
+ * <br>
+ * This class can be used to map an instance of
+ * {@link HttpRequestHandler} matching a particular request URI. Usually the
+ * mapped request handler will be used to process the request with the
+ * specified request URI.
+ *
+ * @since 4.3
+ */
+@ThreadSafe // provided injected dependencies are thread-safe
+public class UriHttpRequestHandlerMapper implements HttpRequestHandlerMapper {
+
+ private final UriPatternMatcher<HttpRequestHandler> matcher;
+
+ protected UriHttpRequestHandlerMapper(final UriPatternMatcher<HttpRequestHandler> matcher) {
+ super();
+ this.matcher = Args.notNull(matcher, "Pattern matcher");
+ }
+
+ public UriHttpRequestHandlerMapper() {
+ this(new UriPatternMatcher<HttpRequestHandler>());
+ }
+
+ /**
+ * Registers the given {@link HttpRequestHandler} as a handler for URIs
+ * matching the given pattern.
+ *
+ * @param pattern the pattern to register the handler for.
+ * @param handler the handler.
+ */
+ public void register(final String pattern, final HttpRequestHandler handler) {
+ Args.notNull(pattern, "Pattern");
+ Args.notNull(handler, "Handler");
+ matcher.register(pattern, handler);
+ }
+
+ /**
+ * Removes registered handler, if exists, for the given pattern.
+ *
+ * @param pattern the pattern to unregister the handler for.
+ */
+ public void unregister(final String pattern) {
+ matcher.unregister(pattern);
+ }
+
+ /**
+ * Extracts request path from the given {@link HttpRequest}
+ */
+ protected String getRequestPath(final HttpRequest request) {
+ String uriPath = request.getRequestLine().getUri();
+ int index = uriPath.indexOf("?");
+ if (index != -1) {
+ uriPath = uriPath.substring(0, index);
+ } else {
+ index = uriPath.indexOf("#");
+ if (index != -1) {
+ uriPath = uriPath.substring(0, index);
+ }
+ }
+ return uriPath;
+ }
+
+ /**
+ * Looks up a handler matching the given request URI.
+ *
+ * @param request the request
+ * @return handler or <code>null</code> if no match is found.
+ */
+ public HttpRequestHandler lookup(final HttpRequest request) {
+ Args.notNull(request, "HTTP request");
+ return matcher.lookup(getRequestPath(request));
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriPatternMatcher.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriPatternMatcher.java
new file mode 100644
index 000000000..77c46a70c
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/UriPatternMatcher.java
@@ -0,0 +1,165 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.protocol;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.boye.httpclientandroidlib.annotation.GuardedBy;
+import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
+import ch.boye.httpclientandroidlib.util.Args;
+
+/**
+ * Maintains a map of objects keyed by a request URI pattern.
+ * <br>
+ * Patterns may have three formats:
+ * <ul>
+ * <li><code>*</code></li>
+ * <li><code>*&lt;uri&gt;</code></li>
+ * <li><code>&lt;uri&gt;*</code></li>
+ * </ul>
+ * <br>
+ * This class can be used to resolve an object matching a particular request
+ * URI.
+ *
+ * @since 4.0
+ */
+@ThreadSafe
+public class UriPatternMatcher<T> {
+
+ @GuardedBy("this")
+ private final Map<String, T> map;
+
+ public UriPatternMatcher() {
+ super();
+ this.map = new HashMap<String, T>();
+ }
+
+ /**
+ * Registers the given object for URIs matching the given pattern.
+ *
+ * @param pattern the pattern to register the handler for.
+ * @param obj the object.
+ */
+ public synchronized void register(final String pattern, final T obj) {
+ Args.notNull(pattern, "URI request pattern");
+ this.map.put(pattern, obj);
+ }
+
+ /**
+ * Removes registered object, if exists, for the given pattern.
+ *
+ * @param pattern the pattern to unregister.
+ */
+ public synchronized void unregister(final String pattern) {
+ if (pattern == null) {
+ return;
+ }
+ this.map.remove(pattern);
+ }
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ public synchronized void setHandlers(final Map<String, T> map) {
+ Args.notNull(map, "Map of handlers");
+ this.map.clear();
+ this.map.putAll(map);
+ }
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ public synchronized void setObjects(final Map<String, T> map) {
+ Args.notNull(map, "Map of handlers");
+ this.map.clear();
+ this.map.putAll(map);
+ }
+
+ /**
+ * @deprecated (4.1) do not use
+ */
+ @Deprecated
+ public synchronized Map<String, T> getObjects() {
+ return this.map;
+ }
+
+ /**
+ * Looks up an object matching the given request path.
+ *
+ * @param path the request path
+ * @return object or <code>null</code> if no match is found.
+ */
+ public synchronized T lookup(final String path) {
+ Args.notNull(path, "Request path");
+ // direct match?
+ T obj = this.map.get(path);
+ if (obj == null) {
+ // pattern match?
+ String bestMatch = null;
+ for (final String pattern : this.map.keySet()) {
+ if (matchUriRequestPattern(pattern, path)) {
+ // we have a match. is it any better?
+ if (bestMatch == null
+ || (bestMatch.length() < pattern.length())
+ || (bestMatch.length() == pattern.length() && pattern.endsWith("*"))) {
+ obj = this.map.get(pattern);
+ bestMatch = pattern;
+ }
+ }
+ }
+ }
+ return obj;
+ }
+
+ /**
+ * Tests if the given request path matches the given pattern.
+ *
+ * @param pattern the pattern
+ * @param path the request path
+ * @return <code>true</code> if the request URI matches the pattern,
+ * <code>false</code> otherwise.
+ */
+ protected boolean matchUriRequestPattern(final String pattern, final String path) {
+ if (pattern.equals("*")) {
+ return true;
+ } else {
+ return
+ (pattern.endsWith("*") && path.startsWith(pattern.substring(0, pattern.length() - 1))) ||
+ (pattern.startsWith("*") && path.endsWith(pattern.substring(1, pattern.length())));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this.map.toString();
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/package-info.java
new file mode 100644
index 000000000..97fcbfdc1
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Core HTTP protocol execution framework and HTTP protocol handlers
+ * for synchronous, blocking communication.
+ */
+package ch.boye.httpclientandroidlib.protocol;
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Args.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Args.java
new file mode 100644
index 000000000..16e6ec4bf
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Args.java
@@ -0,0 +1,111 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+import java.util.Collection;
+
+public class Args {
+
+ public static void check(final boolean expression, final String message) {
+ if (!expression) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ public static void check(final boolean expression, final String message, final Object... args) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.format(message, args));
+ }
+ }
+
+ public static <T> T notNull(final T argument, final String name) {
+ if (argument == null) {
+ throw new IllegalArgumentException(name + " may not be null");
+ }
+ return argument;
+ }
+
+ public static <T extends CharSequence> T notEmpty(final T argument, final String name) {
+ if (argument == null) {
+ throw new IllegalArgumentException(name + " may not be null");
+ }
+ if (TextUtils.isEmpty(argument)) {
+ throw new IllegalArgumentException(name + " may not be empty");
+ }
+ return argument;
+ }
+
+ public static <T extends CharSequence> T notBlank(final T argument, final String name) {
+ if (argument == null) {
+ throw new IllegalArgumentException(name + " may not be null");
+ }
+ if (TextUtils.isBlank(argument)) {
+ throw new IllegalArgumentException(name + " may not be blank");
+ }
+ return argument;
+ }
+
+ public static <E, T extends Collection<E>> T notEmpty(final T argument, final String name) {
+ if (argument == null) {
+ throw new IllegalArgumentException(name + " may not be null");
+ }
+ if (argument.isEmpty()) {
+ throw new IllegalArgumentException(name + " may not be empty");
+ }
+ return argument;
+ }
+
+ public static int positive(final int n, final String name) {
+ if (n <= 0) {
+ throw new IllegalArgumentException(name + " may not be negative or zero");
+ }
+ return n;
+ }
+
+ public static long positive(final long n, final String name) {
+ if (n <= 0) {
+ throw new IllegalArgumentException(name + " may not be negative or zero");
+ }
+ return n;
+ }
+
+ public static int notNegative(final int n, final String name) {
+ if (n < 0) {
+ throw new IllegalArgumentException(name + " may not be negative");
+ }
+ return n;
+ }
+
+ public static long notNegative(final long n, final String name) {
+ if (n < 0) {
+ throw new IllegalArgumentException(name + " may not be negative");
+ }
+ return n;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Asserts.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Asserts.java
new file mode 100644
index 000000000..4515e1577
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/Asserts.java
@@ -0,0 +1,62 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+public class Asserts {
+
+ public static void check(final boolean expression, final String message) {
+ if (!expression) {
+ throw new IllegalStateException(message);
+ }
+ }
+
+ public static void check(final boolean expression, final String message, final Object... args) {
+ if (!expression) {
+ throw new IllegalStateException(String.format(message, args));
+ }
+ }
+
+ public static void notNull(final Object object, final String name) {
+ if (object == null) {
+ throw new IllegalStateException(name + " is null");
+ }
+ }
+
+ public static void notEmpty(final CharSequence s, final String name) {
+ if (TextUtils.isEmpty(s)) {
+ throw new IllegalStateException(name + " is empty");
+ }
+ }
+
+ public static void notBlank(final CharSequence s, final String name) {
+ if (TextUtils.isBlank(s)) {
+ throw new IllegalStateException(name + " is blank");
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ByteArrayBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ByteArrayBuffer.java
new file mode 100644
index 000000000..cbf7c943d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ByteArrayBuffer.java
@@ -0,0 +1,347 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+
+/**
+ * A resizable byte array.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public final class ByteArrayBuffer implements Serializable {
+
+ private static final long serialVersionUID = 4359112959524048036L;
+
+ private byte[] buffer;
+ private int len;
+
+ /**
+ * Creates an instance of {@link ByteArrayBuffer} with the given initial
+ * capacity.
+ *
+ * @param capacity the capacity
+ */
+ public ByteArrayBuffer(final int capacity) {
+ super();
+ Args.notNegative(capacity, "Buffer capacity");
+ this.buffer = new byte[capacity];
+ }
+
+ private void expand(final int newlen) {
+ final byte newbuffer[] = new byte[Math.max(this.buffer.length << 1, newlen)];
+ System.arraycopy(this.buffer, 0, newbuffer, 0, this.len);
+ this.buffer = newbuffer;
+ }
+
+ /**
+ * Appends <code>len</code> bytes to this buffer from the given source
+ * array starting at index <code>off</code>. The capacity of the buffer
+ * is increased, if necessary, to accommodate all <code>len</code> bytes.
+ *
+ * @param b the bytes to be appended.
+ * @param off the index of the first byte to append.
+ * @param len the number of bytes to append.
+ * @throws IndexOutOfBoundsException if <code>off</code> if out of
+ * range, <code>len</code> is negative, or
+ * <code>off</code> + <code>len</code> is out of range.
+ */
+ public void append(final byte[] b, final int off, final int len) {
+ if (b == null) {
+ return;
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
+ }
+ if (len == 0) {
+ return;
+ }
+ final int newlen = this.len + len;
+ if (newlen > this.buffer.length) {
+ expand(newlen);
+ }
+ System.arraycopy(b, off, this.buffer, this.len, len);
+ this.len = newlen;
+ }
+
+ /**
+ * Appends <code>b</code> byte to this buffer. The capacity of the buffer
+ * is increased, if necessary, to accommodate the additional byte.
+ *
+ * @param b the byte to be appended.
+ */
+ public void append(final int b) {
+ final int newlen = this.len + 1;
+ if (newlen > this.buffer.length) {
+ expand(newlen);
+ }
+ this.buffer[this.len] = (byte)b;
+ this.len = newlen;
+ }
+
+ /**
+ * Appends <code>len</code> chars to this buffer from the given source
+ * array starting at index <code>off</code>. The capacity of the buffer
+ * is increased if necessary to accommodate all <code>len</code> chars.
+ * <p>
+ * The chars are converted to bytes using simple cast.
+ *
+ * @param b the chars to be appended.
+ * @param off the index of the first char to append.
+ * @param len the number of bytes to append.
+ * @throws IndexOutOfBoundsException if <code>off</code> if out of
+ * range, <code>len</code> is negative, or
+ * <code>off</code> + <code>len</code> is out of range.
+ */
+ public void append(final char[] b, final int off, final int len) {
+ if (b == null) {
+ return;
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
+ }
+ if (len == 0) {
+ return;
+ }
+ final int oldlen = this.len;
+ final int newlen = oldlen + len;
+ if (newlen > this.buffer.length) {
+ expand(newlen);
+ }
+ for (int i1 = off, i2 = oldlen; i2 < newlen; i1++, i2++) {
+ this.buffer[i2] = (byte) b[i1];
+ }
+ this.len = newlen;
+ }
+
+ /**
+ * Appends <code>len</code> chars to this buffer from the given source
+ * char array buffer starting at index <code>off</code>. The capacity
+ * of the buffer is increased if necessary to accommodate all
+ * <code>len</code> chars.
+ * <p>
+ * The chars are converted to bytes using simple cast.
+ *
+ * @param b the chars to be appended.
+ * @param off the index of the first char to append.
+ * @param len the number of bytes to append.
+ * @throws IndexOutOfBoundsException if <code>off</code> if out of
+ * range, <code>len</code> is negative, or
+ * <code>off</code> + <code>len</code> is out of range.
+ */
+ public void append(final CharArrayBuffer b, final int off, final int len) {
+ if (b == null) {
+ return;
+ }
+ append(b.buffer(), off, len);
+ }
+
+ /**
+ * Clears content of the buffer. The underlying byte array is not resized.
+ */
+ public void clear() {
+ this.len = 0;
+ }
+
+ /**
+ * Converts the content of this buffer to an array of bytes.
+ *
+ * @return byte array
+ */
+ public byte[] toByteArray() {
+ final byte[] b = new byte[this.len];
+ if (this.len > 0) {
+ System.arraycopy(this.buffer, 0, b, 0, this.len);
+ }
+ return b;
+ }
+
+ /**
+ * Returns the <code>byte</code> value in this buffer at the specified
+ * index. The index argument must be greater than or equal to
+ * <code>0</code>, and less than the length of this buffer.
+ *
+ * @param i the index of the desired byte value.
+ * @return the byte value at the specified index.
+ * @throws IndexOutOfBoundsException if <code>index</code> is
+ * negative or greater than or equal to {@link #length()}.
+ */
+ public int byteAt(final int i) {
+ return this.buffer[i];
+ }
+
+ /**
+ * Returns the current capacity. The capacity is the amount of storage
+ * available for newly appended bytes, beyond which an allocation
+ * will occur.
+ *
+ * @return the current capacity
+ */
+ public int capacity() {
+ return this.buffer.length;
+ }
+
+ /**
+ * Returns the length of the buffer (byte count).
+ *
+ * @return the length of the buffer
+ */
+ public int length() {
+ return this.len;
+ }
+
+ /**
+ * Ensures that the capacity is at least equal to the specified minimum.
+ * If the current capacity is less than the argument, then a new internal
+ * array is allocated with greater capacity. If the <code>required</code>
+ * argument is non-positive, this method takes no action.
+ *
+ * @param required the minimum required capacity.
+ *
+ * @since 4.1
+ */
+ public void ensureCapacity(final int required) {
+ if (required <= 0) {
+ return;
+ }
+ final int available = this.buffer.length - this.len;
+ if (required > available) {
+ expand(this.len + required);
+ }
+ }
+
+ /**
+ * Returns reference to the underlying byte array.
+ *
+ * @return the byte array.
+ */
+ public byte[] buffer() {
+ return this.buffer;
+ }
+
+ /**
+ * Sets the length of the buffer. The new length value is expected to be
+ * less than the current capacity and greater than or equal to
+ * <code>0</code>.
+ *
+ * @param len the new length
+ * @throws IndexOutOfBoundsException if the
+ * <code>len</code> argument is greater than the current
+ * capacity of the buffer or less than <code>0</code>.
+ */
+ public void setLength(final int len) {
+ if (len < 0 || len > this.buffer.length) {
+ throw new IndexOutOfBoundsException("len: "+len+" < 0 or > buffer len: "+this.buffer.length);
+ }
+ this.len = len;
+ }
+
+ /**
+ * Returns <code>true</code> if this buffer is empty, that is, its
+ * {@link #length()} is equal to <code>0</code>.
+ * @return <code>true</code> if this buffer is empty, <code>false</code>
+ * otherwise.
+ */
+ public boolean isEmpty() {
+ return this.len == 0;
+ }
+
+ /**
+ * Returns <code>true</code> if this buffer is full, that is, its
+ * {@link #length()} is equal to its {@link #capacity()}.
+ * @return <code>true</code> if this buffer is full, <code>false</code>
+ * otherwise.
+ */
+ public boolean isFull() {
+ return this.len == this.buffer.length;
+ }
+
+ /**
+ * Returns the index within this buffer of the first occurrence of the
+ * specified byte, starting the search at the specified
+ * <code>beginIndex</code> and finishing at <code>endIndex</code>.
+ * If no such byte occurs in this buffer within the specified bounds,
+ * <code>-1</code> is returned.
+ * <p>
+ * There is no restriction on the value of <code>beginIndex</code> and
+ * <code>endIndex</code>. If <code>beginIndex</code> is negative,
+ * it has the same effect as if it were zero. If <code>endIndex</code> is
+ * greater than {@link #length()}, it has the same effect as if it were
+ * {@link #length()}. If the <code>beginIndex</code> is greater than
+ * the <code>endIndex</code>, <code>-1</code> is returned.
+ *
+ * @param b the byte to search for.
+ * @param from the index to start the search from.
+ * @param to the index to finish the search at.
+ * @return the index of the first occurrence of the byte in the buffer
+ * within the given bounds, or <code>-1</code> if the byte does
+ * not occur.
+ *
+ * @since 4.1
+ */
+ public int indexOf(final byte b, final int from, final int to) {
+ int beginIndex = from;
+ if (beginIndex < 0) {
+ beginIndex = 0;
+ }
+ int endIndex = to;
+ if (endIndex > this.len) {
+ endIndex = this.len;
+ }
+ if (beginIndex > endIndex) {
+ return -1;
+ }
+ for (int i = beginIndex; i < endIndex; i++) {
+ if (this.buffer[i] == b) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index within this buffer of the first occurrence of the
+ * specified byte, starting the search at <code>0</code> and finishing
+ * at {@link #length()}. If no such byte occurs in this buffer within
+ * those bounds, <code>-1</code> is returned.
+ *
+ * @param b the byte to search for.
+ * @return the index of the first occurrence of the byte in the
+ * buffer, or <code>-1</code> if the byte does not occur.
+ *
+ * @since 4.1
+ */
+ public int indexOf(final byte b) {
+ return indexOf(b, 0, this.len);
+ }
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharArrayBuffer.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharArrayBuffer.java
new file mode 100644
index 000000000..88dc36c7a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharArrayBuffer.java
@@ -0,0 +1,464 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+import java.io.Serializable;
+
+import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * A resizable char array.
+ *
+ * @since 4.0
+ */
+@NotThreadSafe
+public final class CharArrayBuffer implements Serializable {
+
+ private static final long serialVersionUID = -6208952725094867135L;
+
+ private char[] buffer;
+ private int len;
+
+ /**
+ * Creates an instance of {@link CharArrayBuffer} with the given initial
+ * capacity.
+ *
+ * @param capacity the capacity
+ */
+ public CharArrayBuffer(final int capacity) {
+ super();
+ Args.notNegative(capacity, "Buffer capacity");
+ this.buffer = new char[capacity];
+ }
+
+ private void expand(final int newlen) {
+ final char newbuffer[] = new char[Math.max(this.buffer.length << 1, newlen)];
+ System.arraycopy(this.buffer, 0, newbuffer, 0, this.len);
+ this.buffer = newbuffer;
+ }
+
+ /**
+ * Appends <code>len</code> chars to this buffer from the given source
+ * array starting at index <code>off</code>. The capacity of the buffer
+ * is increased, if necessary, to accommodate all <code>len</code> chars.
+ *
+ * @param b the chars to be appended.
+ * @param off the index of the first char to append.
+ * @param len the number of chars to append.
+ * @throws IndexOutOfBoundsException if <code>off</code> is out of
+ * range, <code>len</code> is negative, or
+ * <code>off</code> + <code>len</code> is out of range.
+ */
+ public void append(final char[] b, final int off, final int len) {
+ if (b == null) {
+ return;
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
+ }
+ if (len == 0) {
+ return;
+ }
+ final int newlen = this.len + len;
+ if (newlen > this.buffer.length) {
+ expand(newlen);
+ }
+ System.arraycopy(b, off, this.buffer, this.len, len);
+ this.len = newlen;
+ }
+
+ /**
+ * Appends chars of the given string to this buffer. The capacity of the
+ * buffer is increased, if necessary, to accommodate all chars.
+ *
+ * @param str the string.
+ */
+ public void append(final String str) {
+ final String s = str != null ? str : "null";
+ final int strlen = s.length();
+ final int newlen = this.len + strlen;
+ if (newlen > this.buffer.length) {
+ expand(newlen);
+ }
+ s.getChars(0, strlen, this.buffer, this.len);
+ this.len = newlen;
+ }
+
+ /**
+ * Appends <code>len</code> chars to this buffer from the given source
+ * buffer starting at index <code>off</code>. The capacity of the
+ * destination buffer is increased, if necessary, to accommodate all
+ * <code>len</code> chars.
+ *
+ * @param b the source buffer to be appended.
+ * @param off the index of the first char to append.
+ * @param len the number of chars to append.
+ * @throws IndexOutOfBoundsException if <code>off</code> is out of
+ * range, <code>len</code> is negative, or
+ * <code>off</code> + <code>len</code> is out of range.
+ */
+ public void append(final CharArrayBuffer b, final int off, final int len) {
+ if (b == null) {
+ return;
+ }
+ append(b.buffer, off, len);
+ }
+
+ /**
+ * Appends all chars to this buffer from the given source buffer starting
+ * at index <code>0</code>. The capacity of the destination buffer is
+ * increased, if necessary, to accommodate all {@link #length()} chars.
+ *
+ * @param b the source buffer to be appended.
+ */
+ public void append(final CharArrayBuffer b) {
+ if (b == null) {
+ return;
+ }
+ append(b.buffer,0, b.len);
+ }
+
+ /**
+ * Appends <code>ch</code> char to this buffer. The capacity of the buffer
+ * is increased, if necessary, to accommodate the additional char.
+ *
+ * @param ch the char to be appended.
+ */
+ public void append(final char ch) {
+ final int newlen = this.len + 1;
+ if (newlen > this.buffer.length) {
+ expand(newlen);
+ }
+ this.buffer[this.len] = ch;
+ this.len = newlen;
+ }
+
+ /**
+ * Appends <code>len</code> bytes to this buffer from the given source
+ * array starting at index <code>off</code>. The capacity of the buffer
+ * is increased, if necessary, to accommodate all <code>len</code> bytes.
+ * <p>
+ * The bytes are converted to chars using simple cast.
+ *
+ * @param b the bytes to be appended.
+ * @param off the index of the first byte to append.
+ * @param len the number of bytes to append.
+ * @throws IndexOutOfBoundsException if <code>off</code> is out of
+ * range, <code>len</code> is negative, or
+ * <code>off</code> + <code>len</code> is out of range.
+ */
+ public void append(final byte[] b, final int off, final int len) {
+ if (b == null) {
+ return;
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
+ }
+ if (len == 0) {
+ return;
+ }
+ final int oldlen = this.len;
+ final int newlen = oldlen + len;
+ if (newlen > this.buffer.length) {
+ expand(newlen);
+ }
+ for (int i1 = off, i2 = oldlen; i2 < newlen; i1++, i2++) {
+ this.buffer[i2] = (char) (b[i1] & 0xff);
+ }
+ this.len = newlen;
+ }
+
+ /**
+ * Appends <code>len</code> bytes to this buffer from the given source
+ * array starting at index <code>off</code>. The capacity of the buffer
+ * is increased, if necessary, to accommodate all <code>len</code> bytes.
+ * <p>
+ * The bytes are converted to chars using simple cast.
+ *
+ * @param b the bytes to be appended.
+ * @param off the index of the first byte to append.
+ * @param len the number of bytes to append.
+ * @throws IndexOutOfBoundsException if <code>off</code> is out of
+ * range, <code>len</code> is negative, or
+ * <code>off</code> + <code>len</code> is out of range.
+ */
+ public void append(final ByteArrayBuffer b, final int off, final int len) {
+ if (b == null) {
+ return;
+ }
+ append(b.buffer(), off, len);
+ }
+
+ /**
+ * Appends chars of the textual representation of the given object to this
+ * buffer. The capacity of the buffer is increased, if necessary, to
+ * accommodate all chars.
+ *
+ * @param obj the object.
+ */
+ public void append(final Object obj) {
+ append(String.valueOf(obj));
+ }
+
+ /**
+ * Clears content of the buffer. The underlying char array is not resized.
+ */
+ public void clear() {
+ this.len = 0;
+ }
+
+ /**
+ * Converts the content of this buffer to an array of chars.
+ *
+ * @return char array
+ */
+ public char[] toCharArray() {
+ final char[] b = new char[this.len];
+ if (this.len > 0) {
+ System.arraycopy(this.buffer, 0, b, 0, this.len);
+ }
+ return b;
+ }
+
+ /**
+ * Returns the <code>char</code> value in this buffer at the specified
+ * index. The index argument must be greater than or equal to
+ * <code>0</code>, and less than the length of this buffer.
+ *
+ * @param i the index of the desired char value.
+ * @return the char value at the specified index.
+ * @throws IndexOutOfBoundsException if <code>index</code> is
+ * negative or greater than or equal to {@link #length()}.
+ */
+ public char charAt(final int i) {
+ return this.buffer[i];
+ }
+
+ /**
+ * Returns reference to the underlying char array.
+ *
+ * @return the char array.
+ */
+ public char[] buffer() {
+ return this.buffer;
+ }
+
+ /**
+ * Returns the current capacity. The capacity is the amount of storage
+ * available for newly appended chars, beyond which an allocation will
+ * occur.
+ *
+ * @return the current capacity
+ */
+ public int capacity() {
+ return this.buffer.length;
+ }
+
+ /**
+ * Returns the length of the buffer (char count).
+ *
+ * @return the length of the buffer
+ */
+ public int length() {
+ return this.len;
+ }
+
+ /**
+ * Ensures that the capacity is at least equal to the specified minimum.
+ * If the current capacity is less than the argument, then a new internal
+ * array is allocated with greater capacity. If the <code>required</code>
+ * argument is non-positive, this method takes no action.
+ *
+ * @param required the minimum required capacity.
+ */
+ public void ensureCapacity(final int required) {
+ if (required <= 0) {
+ return;
+ }
+ final int available = this.buffer.length - this.len;
+ if (required > available) {
+ expand(this.len + required);
+ }
+ }
+
+ /**
+ * Sets the length of the buffer. The new length value is expected to be
+ * less than the current capacity and greater than or equal to
+ * <code>0</code>.
+ *
+ * @param len the new length
+ * @throws IndexOutOfBoundsException if the
+ * <code>len</code> argument is greater than the current
+ * capacity of the buffer or less than <code>0</code>.
+ */
+ public void setLength(final int len) {
+ if (len < 0 || len > this.buffer.length) {
+ throw new IndexOutOfBoundsException("len: "+len+" < 0 or > buffer len: "+this.buffer.length);
+ }
+ this.len = len;
+ }
+
+ /**
+ * Returns <code>true</code> if this buffer is empty, that is, its
+ * {@link #length()} is equal to <code>0</code>.
+ * @return <code>true</code> if this buffer is empty, <code>false</code>
+ * otherwise.
+ */
+ public boolean isEmpty() {
+ return this.len == 0;
+ }
+
+ /**
+ * Returns <code>true</code> if this buffer is full, that is, its
+ * {@link #length()} is equal to its {@link #capacity()}.
+ * @return <code>true</code> if this buffer is full, <code>false</code>
+ * otherwise.
+ */
+ public boolean isFull() {
+ return this.len == this.buffer.length;
+ }
+
+ /**
+ * Returns the index within this buffer of the first occurrence of the
+ * specified character, starting the search at the specified
+ * <code>beginIndex</code> and finishing at <code>endIndex</code>.
+ * If no such character occurs in this buffer within the specified bounds,
+ * <code>-1</code> is returned.
+ * <p>
+ * There is no restriction on the value of <code>beginIndex</code> and
+ * <code>endIndex</code>. If <code>beginIndex</code> is negative,
+ * it has the same effect as if it were zero. If <code>endIndex</code> is
+ * greater than {@link #length()}, it has the same effect as if it were
+ * {@link #length()}. If the <code>beginIndex</code> is greater than
+ * the <code>endIndex</code>, <code>-1</code> is returned.
+ *
+ * @param ch the char to search for.
+ * @param from the index to start the search from.
+ * @param to the index to finish the search at.
+ * @return the index of the first occurrence of the character in the buffer
+ * within the given bounds, or <code>-1</code> if the character does
+ * not occur.
+ */
+ public int indexOf(final int ch, final int from, final int to) {
+ int beginIndex = from;
+ if (beginIndex < 0) {
+ beginIndex = 0;
+ }
+ int endIndex = to;
+ if (endIndex > this.len) {
+ endIndex = this.len;
+ }
+ if (beginIndex > endIndex) {
+ return -1;
+ }
+ for (int i = beginIndex; i < endIndex; i++) {
+ if (this.buffer[i] == ch) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index within this buffer of the first occurrence of the
+ * specified character, starting the search at <code>0</code> and finishing
+ * at {@link #length()}. If no such character occurs in this buffer within
+ * those bounds, <code>-1</code> is returned.
+ *
+ * @param ch the char to search for.
+ * @return the index of the first occurrence of the character in the
+ * buffer, or <code>-1</code> if the character does not occur.
+ */
+ public int indexOf(final int ch) {
+ return indexOf(ch, 0, this.len);
+ }
+
+ /**
+ * Returns a substring of this buffer. The substring begins at the specified
+ * <code>beginIndex</code> and extends to the character at index
+ * <code>endIndex - 1</code>.
+ *
+ * @param beginIndex the beginning index, inclusive.
+ * @param endIndex the ending index, exclusive.
+ * @return the specified substring.
+ * @exception StringIndexOutOfBoundsException if the
+ * <code>beginIndex</code> is negative, or
+ * <code>endIndex</code> is larger than the length of this
+ * buffer, or <code>beginIndex</code> is larger than
+ * <code>endIndex</code>.
+ */
+ public String substring(final int beginIndex, final int endIndex) {
+ return new String(this.buffer, beginIndex, endIndex - beginIndex);
+ }
+
+ /**
+ * Returns a substring of this buffer with leading and trailing whitespace
+ * omitted. The substring begins with the first non-whitespace character
+ * from <code>beginIndex</code> and extends to the last
+ * non-whitespace character with the index lesser than
+ * <code>endIndex</code>.
+ *
+ * @param from the beginning index, inclusive.
+ * @param to the ending index, exclusive.
+ * @return the specified substring.
+ * @exception IndexOutOfBoundsException if the
+ * <code>beginIndex</code> is negative, or
+ * <code>endIndex</code> is larger than the length of this
+ * buffer, or <code>beginIndex</code> is larger than
+ * <code>endIndex</code>.
+ */
+ public String substringTrimmed(final int from, final int to) {
+ int beginIndex = from;
+ int endIndex = to;
+ if (beginIndex < 0) {
+ throw new IndexOutOfBoundsException("Negative beginIndex: "+beginIndex);
+ }
+ if (endIndex > this.len) {
+ throw new IndexOutOfBoundsException("endIndex: "+endIndex+" > length: "+this.len);
+ }
+ if (beginIndex > endIndex) {
+ throw new IndexOutOfBoundsException("beginIndex: "+beginIndex+" > endIndex: "+endIndex);
+ }
+ while (beginIndex < endIndex && HTTP.isWhitespace(this.buffer[beginIndex])) {
+ beginIndex++;
+ }
+ while (endIndex > beginIndex && HTTP.isWhitespace(this.buffer[endIndex - 1])) {
+ endIndex--;
+ }
+ return new String(this.buffer, beginIndex, endIndex - beginIndex);
+ }
+
+ @Override
+ public String toString() {
+ return new String(this.buffer, 0, this.len);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharsetUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharsetUtils.java
new file mode 100644
index 000000000..e6e75e0ad
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/CharsetUtils.java
@@ -0,0 +1,58 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+public class CharsetUtils {
+
+ public static Charset lookup(final String name) {
+ if (name == null) {
+ return null;
+ }
+ try {
+ return Charset.forName(name);
+ } catch (final UnsupportedCharsetException ex) {
+ return null;
+ }
+ }
+
+ public static Charset get(final String name) throws UnsupportedEncodingException {
+ if (name == null) {
+ return null;
+ }
+ try {
+ return Charset.forName(name);
+ } catch (final UnsupportedCharsetException ex) {
+ throw new UnsupportedEncodingException(name);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EncodingUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EncodingUtils.java
new file mode 100644
index 000000000..964553909
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EncodingUtils.java
@@ -0,0 +1,152 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.util;
+
+import java.io.UnsupportedEncodingException;
+
+import ch.boye.httpclientandroidlib.Consts;
+
+/**
+ * The home for utility methods that handle various encoding tasks.
+ *
+ *
+ * @since 4.0
+ */
+public final class EncodingUtils {
+
+ /**
+ * Converts the byte array of HTTP content characters to a string. If
+ * the specified charset is not supported, default system encoding
+ * is used.
+ *
+ * @param data the byte array to be encoded
+ * @param offset the index of the first byte to encode
+ * @param length the number of bytes to encode
+ * @param charset the desired character encoding
+ * @return The result of the conversion.
+ */
+ public static String getString(
+ final byte[] data,
+ final int offset,
+ final int length,
+ final String charset) {
+ Args.notNull(data, "Input");
+ Args.notEmpty(charset, "Charset");
+ try {
+ return new String(data, offset, length, charset);
+ } catch (final UnsupportedEncodingException e) {
+ return new String(data, offset, length);
+ }
+ }
+
+
+ /**
+ * Converts the byte array of HTTP content characters to a string. If
+ * the specified charset is not supported, default system encoding
+ * is used.
+ *
+ * @param data the byte array to be encoded
+ * @param charset the desired character encoding
+ * @return The result of the conversion.
+ */
+ public static String getString(final byte[] data, final String charset) {
+ Args.notNull(data, "Input");
+ return getString(data, 0, data.length, charset);
+ }
+
+ /**
+ * Converts the specified string to a byte array. If the charset is not supported the
+ * default system charset is used.
+ *
+ * @param data the string to be encoded
+ * @param charset the desired character encoding
+ * @return The resulting byte array.
+ */
+ public static byte[] getBytes(final String data, final String charset) {
+ Args.notNull(data, "Input");
+ Args.notEmpty(charset, "Charset");
+ try {
+ return data.getBytes(charset);
+ } catch (final UnsupportedEncodingException e) {
+ return data.getBytes();
+ }
+ }
+
+ /**
+ * Converts the specified string to byte array of ASCII characters.
+ *
+ * @param data the string to be encoded
+ * @return The string as a byte array.
+ */
+ public static byte[] getAsciiBytes(final String data) {
+ Args.notNull(data, "Input");
+ try {
+ return data.getBytes(Consts.ASCII.name());
+ } catch (final UnsupportedEncodingException e) {
+ throw new Error("ASCII not supported");
+ }
+ }
+
+ /**
+ * Converts the byte array of ASCII characters to a string. This method is
+ * to be used when decoding content of HTTP elements (such as response
+ * headers)
+ *
+ * @param data the byte array to be encoded
+ * @param offset the index of the first byte to encode
+ * @param length the number of bytes to encode
+ * @return The string representation of the byte array
+ */
+ public static String getAsciiString(final byte[] data, final int offset, final int length) {
+ Args.notNull(data, "Input");
+ try {
+ return new String(data, offset, length, Consts.ASCII.name());
+ } catch (final UnsupportedEncodingException e) {
+ throw new Error("ASCII not supported");
+ }
+ }
+
+ /**
+ * Converts the byte array of ASCII characters to a string. This method is
+ * to be used when decoding content of HTTP elements (such as response
+ * headers)
+ *
+ * @param data the byte array to be encoded
+ * @return The string representation of the byte array
+ */
+ public static String getAsciiString(final byte[] data) {
+ Args.notNull(data, "Input");
+ return getAsciiString(data, 0, data.length);
+ }
+
+ /**
+ * This class should not be instantiated.
+ */
+ private EncodingUtils() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EntityUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EntityUtils.java
new file mode 100644
index 000000000..6bc19ef1e
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/EntityUtils.java
@@ -0,0 +1,291 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import ch.boye.httpclientandroidlib.HeaderElement;
+import ch.boye.httpclientandroidlib.HttpEntity;
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.NameValuePair;
+import ch.boye.httpclientandroidlib.ParseException;
+import ch.boye.httpclientandroidlib.entity.ContentType;
+import ch.boye.httpclientandroidlib.protocol.HTTP;
+
+/**
+ * Static helpers for dealing with {@link HttpEntity}s.
+ *
+ * @since 4.0
+ */
+public final class EntityUtils {
+
+ private EntityUtils() {
+ }
+
+ /**
+ * Ensures that the entity content is fully consumed and the content stream, if exists,
+ * is closed. The process is done, <i>quietly</i> , without throwing any IOException.
+ *
+ * @param entity the entity to consume.
+ *
+ *
+ * @since 4.2
+ */
+ public static void consumeQuietly(final HttpEntity entity) {
+ try {
+ consume(entity);
+ } catch (final IOException ignore) {
+ }
+ }
+
+ /**
+ * Ensures that the entity content is fully consumed and the content stream, if exists,
+ * is closed.
+ *
+ * @param entity the entity to consume.
+ * @throws IOException if an error occurs reading the input stream
+ *
+ * @since 4.1
+ */
+ public static void consume(final HttpEntity entity) throws IOException {
+ if (entity == null) {
+ return;
+ }
+ if (entity.isStreaming()) {
+ final InputStream instream = entity.getContent();
+ if (instream != null) {
+ instream.close();
+ }
+ }
+ }
+
+ /**
+ * Updates an entity in a response by first consuming an existing entity, then setting the new one.
+ *
+ * @param response the response with an entity to update; must not be null.
+ * @param entity the entity to set in the response.
+ * @throws IOException if an error occurs while reading the input stream on the existing
+ * entity.
+ * @throws IllegalArgumentException if response is null.
+ *
+ * @since 4.3
+ */
+ public static void updateEntity(
+ final HttpResponse response, final HttpEntity entity) throws IOException {
+ Args.notNull(response, "Response");
+ consume(response.getEntity());
+ response.setEntity(entity);
+ }
+
+ /**
+ * Read the contents of an entity and return it as a byte array.
+ *
+ * @param entity the entity to read from=
+ * @return byte array containing the entity content. May be null if
+ * {@link HttpEntity#getContent()} is null.
+ * @throws IOException if an error occurs reading the input stream
+ * @throws IllegalArgumentException if entity is null or if content length > Integer.MAX_VALUE
+ */
+ public static byte[] toByteArray(final HttpEntity entity) throws IOException {
+ Args.notNull(entity, "Entity");
+ final InputStream instream = entity.getContent();
+ if (instream == null) {
+ return null;
+ }
+ try {
+ Args.check(entity.getContentLength() <= Integer.MAX_VALUE,
+ "HTTP entity too large to be buffered in memory");
+ int i = (int)entity.getContentLength();
+ if (i < 0) {
+ i = 4096;
+ }
+ final ByteArrayBuffer buffer = new ByteArrayBuffer(i);
+ final byte[] tmp = new byte[4096];
+ int l;
+ while((l = instream.read(tmp)) != -1) {
+ buffer.append(tmp, 0, l);
+ }
+ return buffer.toByteArray();
+ } finally {
+ instream.close();
+ }
+ }
+
+ /**
+ * Obtains character set of the entity, if known.
+ *
+ * @param entity must not be null
+ * @return the character set, or null if not found
+ * @throws ParseException if header elements cannot be parsed
+ * @throws IllegalArgumentException if entity is null
+ *
+ * @deprecated (4.1.3) use {@link ContentType#getOrDefault(HttpEntity)}
+ */
+ @Deprecated
+ public static String getContentCharSet(final HttpEntity entity) throws ParseException {
+ Args.notNull(entity, "Entity");
+ String charset = null;
+ if (entity.getContentType() != null) {
+ final HeaderElement values[] = entity.getContentType().getElements();
+ if (values.length > 0) {
+ final NameValuePair param = values[0].getParameterByName("charset");
+ if (param != null) {
+ charset = param.getValue();
+ }
+ }
+ }
+ return charset;
+ }
+
+ /**
+ * Obtains MIME type of the entity, if known.
+ *
+ * @param entity must not be null
+ * @return the character set, or null if not found
+ * @throws ParseException if header elements cannot be parsed
+ * @throws IllegalArgumentException if entity is null
+ *
+ * @since 4.1
+ *
+ * @deprecated (4.1.3) use {@link ContentType#getOrDefault(HttpEntity)}
+ */
+ @Deprecated
+ public static String getContentMimeType(final HttpEntity entity) throws ParseException {
+ Args.notNull(entity, "Entity");
+ String mimeType = null;
+ if (entity.getContentType() != null) {
+ final HeaderElement values[] = entity.getContentType().getElements();
+ if (values.length > 0) {
+ mimeType = values[0].getName();
+ }
+ }
+ return mimeType;
+ }
+
+ /**
+ * 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.
+ *
+ * @param entity must not be null
+ * @param defaultCharset character set to be applied if none found in the entity
+ * @return the entity content as a String. May be null if
+ * {@link HttpEntity#getContent()} is null.
+ * @throws ParseException if header elements cannot be parsed
+ * @throws IllegalArgumentException if entity is null or if content length > Integer.MAX_VALUE
+ * @throws IOException if an error occurs reading the input stream
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public static String toString(
+ final HttpEntity entity, final Charset defaultCharset) throws IOException, ParseException {
+ Args.notNull(entity, "Entity");
+ final InputStream instream = entity.getContent();
+ if (instream == null) {
+ return null;
+ }
+ try {
+ Args.check(entity.getContentLength() <= Integer.MAX_VALUE,
+ "HTTP entity too large to be buffered in memory");
+ int i = (int)entity.getContentLength();
+ if (i < 0) {
+ i = 4096;
+ }
+ Charset charset = null;
+ try {
+ final ContentType contentType = ContentType.get(entity);
+ if (contentType != null) {
+ charset = contentType.getCharset();
+ }
+ } catch (final UnsupportedCharsetException ex) {
+ throw new UnsupportedEncodingException(ex.getMessage());
+ }
+ if (charset == null) {
+ charset = defaultCharset;
+ }
+ if (charset == null) {
+ charset = HTTP.DEF_CONTENT_CHARSET;
+ }
+ final Reader reader = new InputStreamReader(instream, charset);
+ final CharArrayBuffer buffer = new CharArrayBuffer(i);
+ final char[] tmp = new char[1024];
+ int l;
+ while((l = reader.read(tmp)) != -1) {
+ buffer.append(tmp, 0, l);
+ }
+ return buffer.toString();
+ } finally {
+ instream.close();
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @param entity must not be null
+ * @param defaultCharset character set to be applied if none found in the entity
+ * @return the entity content as a String. May be null if
+ * {@link HttpEntity#getContent()} is null.
+ * @throws ParseException if header elements cannot be parsed
+ * @throws IllegalArgumentException if entity is null or if content length > Integer.MAX_VALUE
+ * @throws IOException if an error occurs reading the input stream
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public static String toString(
+ final HttpEntity entity, final String defaultCharset) throws IOException, ParseException {
+ return toString(entity, defaultCharset != null ? Charset.forName(defaultCharset) : null);
+ }
+
+ /**
+ * Read the contents of an entity and return it as a String.
+ * The content is converted using the character set from the entity (if any),
+ * failing that, "ISO-8859-1" is used.
+ *
+ * @param entity the entity to convert to a string; must not be null
+ * @return String containing the content.
+ * @throws ParseException if header elements cannot be parsed
+ * @throws IllegalArgumentException if entity is null or if content length > Integer.MAX_VALUE
+ * @throws IOException if an error occurs reading the input stream
+ * @throws UnsupportedCharsetException Thrown when the named charset is not available in
+ * this instance of the Java virtual machine
+ */
+ public static String toString(final HttpEntity entity)
+ throws IOException, ParseException {
+ return toString(entity, (Charset)null);
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ExceptionUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ExceptionUtils.java
new file mode 100644
index 000000000..a0c3001ac
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/ExceptionUtils.java
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package ch.boye.httpclientandroidlib.util;
+
+import java.lang.reflect.Method;
+
+/**
+ * The home for utility methods that handle various exception-related tasks.
+ *
+ *
+ * @since 4.0
+ *
+ * @deprecated (4.2) no longer used
+ */
+@Deprecated
+public final class ExceptionUtils {
+
+ /** A reference to Throwable's initCause method, or null if it's not there in this JVM */
+ static private final Method INIT_CAUSE_METHOD = getInitCauseMethod();
+
+ /**
+ * Returns a <code>Method<code> allowing access to
+ * {@link Throwable#initCause(Throwable) initCause} method of {@link Throwable},
+ * or <code>null</code> if the method
+ * does not exist.
+ *
+ * @return A <code>Method<code> for <code>Throwable.initCause</code>, or
+ * <code>null</code> if unavailable.
+ */
+ static private Method getInitCauseMethod() {
+ try {
+ final Class<?>[] paramsClasses = new Class[] { Throwable.class };
+ return Throwable.class.getMethod("initCause", paramsClasses);
+ } catch (final NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ /**
+ * If we're running on JDK 1.4 or later, initialize the cause for the given throwable.
+ *
+ * @param throwable The throwable.
+ * @param cause The cause of the throwable.
+ */
+ public static void initCause(final Throwable throwable, final Throwable cause) {
+ if (INIT_CAUSE_METHOD != null) {
+ try {
+ INIT_CAUSE_METHOD.invoke(throwable, cause);
+ } catch (final Exception e) {
+ // Well, with no logging, the only option is to munch the exception
+ }
+ }
+ }
+
+ private ExceptionUtils() {
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/LangUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/LangUtils.java
new file mode 100644
index 000000000..9a4a29f34
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/LangUtils.java
@@ -0,0 +1,101 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+/**
+ * A set of utility methods to help produce consistent
+ * {@link Object#equals equals} and {@link Object#hashCode hashCode} methods.
+ *
+ *
+ * @since 4.0
+ */
+public final class LangUtils {
+
+ public static final int HASH_SEED = 17;
+ public static final int HASH_OFFSET = 37;
+
+ /** Disabled default constructor. */
+ private LangUtils() {
+ }
+
+ public static int hashCode(final int seed, final int hashcode) {
+ return seed * HASH_OFFSET + hashcode;
+ }
+
+ public static int hashCode(final int seed, final boolean b) {
+ return hashCode(seed, b ? 1 : 0);
+ }
+
+ public static int hashCode(final int seed, final Object obj) {
+ return hashCode(seed, obj != null ? obj.hashCode() : 0);
+ }
+
+ /**
+ * Check if two objects are equal.
+ *
+ * @param obj1 first object to compare, may be {@code null}
+ * @param obj2 second object to compare, may be {@code null}
+ * @return {@code true} if the objects are equal or both null
+ */
+ public static boolean equals(final Object obj1, final Object obj2) {
+ return obj1 == null ? obj2 == null : obj1.equals(obj2);
+ }
+
+ /**
+ * Check if two object arrays are equal.
+ * <p>
+ * <ul>
+ * <li>If both parameters are null, return {@code true}</li>
+ * <li>If one parameter is null, return {@code false}</li>
+ * <li>If the array lengths are different, return {@code false}</li>
+ * <li>Compare array elements using .equals(); return {@code false} if any comparisons fail.</li>
+ * <li>Return {@code true}</li>
+ * </ul>
+ *
+ * @param a1 first array to compare, may be {@code null}
+ * @param a2 second array to compare, may be {@code null}
+ * @return {@code true} if the arrays are equal or both null
+ */
+ public static boolean equals(final Object[] a1, final Object[] a2) {
+ if (a1 == null) {
+ return a2 == null;
+ } else {
+ if (a2 != null && a1.length == a2.length) {
+ for (int i = 0; i < a1.length; i++) {
+ if (!equals(a1[i], a2[i])) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/NetUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/NetUtils.java
new file mode 100644
index 000000000..8d0f4926a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/NetUtils.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+/**
+ * @since 4.3
+ */
+public final class NetUtils {
+
+ public static void formatAddress(
+ final StringBuilder buffer,
+ final SocketAddress socketAddress) {
+ Args.notNull(buffer, "Buffer");
+ Args.notNull(socketAddress, "Socket address");
+ if (socketAddress instanceof InetSocketAddress) {
+ final InetSocketAddress socketaddr = ((InetSocketAddress) socketAddress);
+ final InetAddress inetaddr = socketaddr.getAddress();
+ buffer.append(inetaddr != null ? inetaddr.getHostAddress() : inetaddr)
+ .append(':').append(socketaddr.getPort());
+ } else {
+ buffer.append(socketAddress);
+ }
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/TextUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/TextUtils.java
new file mode 100644
index 000000000..52d8286ff
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/TextUtils.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+/**
+ * @since 4.3
+ */
+public final class TextUtils {
+
+ public static boolean isEmpty(final CharSequence s) {
+ if (s == null) {
+ return true;
+ }
+ return s.length() == 0;
+ }
+
+ public static boolean isBlank(final CharSequence s) {
+ if (s == null) {
+ return true;
+ }
+ for (int i = 0; i < s.length(); i++) {
+ if (!Character.isWhitespace(s.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/VersionInfo.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/VersionInfo.java
new file mode 100644
index 000000000..61042459a
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/VersionInfo.java
@@ -0,0 +1,324 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package ch.boye.httpclientandroidlib.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Provides access to version information for HTTP components.
+ * Static methods are used to extract version information from property
+ * files that are automatically packaged with HTTP component release JARs.
+ * <br/>
+ * All available version information is provided in strings, where
+ * the string format is informal and subject to change without notice.
+ * Version information is provided for debugging output and interpretation
+ * by humans, not for automated processing in applications.
+ *
+ * @since 4.0
+ */
+public class VersionInfo {
+
+ /** A string constant for unavailable information. */
+ public final static String UNAVAILABLE = "UNAVAILABLE";
+
+ /** The filename of the version information files. */
+ public final static String VERSION_PROPERTY_FILE = "version.properties";
+
+ // the property names
+ public final static String PROPERTY_MODULE = "info.module";
+ public final static String PROPERTY_RELEASE = "info.release";
+ public final static String PROPERTY_TIMESTAMP = "info.timestamp";
+
+
+ /** The package that contains the version information. */
+ private final String infoPackage;
+
+ /** The module from the version info. */
+ private final String infoModule;
+
+ /** The release from the version info. */
+ private final String infoRelease;
+
+ /** The timestamp from the version info. */
+ private final String infoTimestamp;
+
+ /** The classloader from which the version info was obtained. */
+ private final String infoClassloader;
+
+
+ /**
+ * Instantiates version information.
+ *
+ * @param pckg the package
+ * @param module the module, or <code>null</code>
+ * @param release the release, or <code>null</code>
+ * @param time the build time, or <code>null</code>
+ * @param clsldr the class loader, or <code>null</code>
+ */
+ protected VersionInfo(final String pckg, final String module,
+ final String release, final String time, final String clsldr) {
+ Args.notNull(pckg, "Package identifier");
+ infoPackage = pckg;
+ infoModule = (module != null) ? module : UNAVAILABLE;
+ infoRelease = (release != null) ? release : UNAVAILABLE;
+ infoTimestamp = (time != null) ? time : UNAVAILABLE;
+ infoClassloader = (clsldr != null) ? clsldr : UNAVAILABLE;
+ }
+
+
+ /**
+ * Obtains the package name.
+ * The package name identifies the module or informal unit.
+ *
+ * @return the package name, never <code>null</code>
+ */
+ public final String getPackage() {
+ return infoPackage;
+ }
+
+ /**
+ * Obtains the name of the versioned module or informal unit.
+ * This data is read from the version information for the package.
+ *
+ * @return the module name, never <code>null</code>
+ */
+ public final String getModule() {
+ return infoModule;
+ }
+
+ /**
+ * Obtains the release of the versioned module or informal unit.
+ * This data is read from the version information for the package.
+ *
+ * @return the release version, never <code>null</code>
+ */
+ public final String getRelease() {
+ return infoRelease;
+ }
+
+ /**
+ * Obtains the timestamp of the versioned module or informal unit.
+ * This data is read from the version information for the package.
+ *
+ * @return the timestamp, never <code>null</code>
+ */
+ public final String getTimestamp() {
+ return infoTimestamp;
+ }
+
+ /**
+ * Obtains the classloader used to read the version information.
+ * This is just the <code>toString</code> output of the classloader,
+ * since the version information should not keep a reference to
+ * the classloader itself. That could prevent garbage collection.
+ *
+ * @return the classloader description, never <code>null</code>
+ */
+ public final String getClassloader() {
+ return infoClassloader;
+ }
+
+
+ /**
+ * Provides the version information in human-readable format.
+ *
+ * @return a string holding this version information
+ */
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder
+ (20 + infoPackage.length() + infoModule.length() +
+ infoRelease.length() + infoTimestamp.length() +
+ infoClassloader.length());
+
+ sb.append("VersionInfo(")
+ .append(infoPackage).append(':').append(infoModule);
+
+ // If version info is missing, a single "UNAVAILABLE" for the module
+ // is sufficient. Everything else just clutters the output.
+ if (!UNAVAILABLE.equals(infoRelease)) {
+ sb.append(':').append(infoRelease);
+ }
+ if (!UNAVAILABLE.equals(infoTimestamp)) {
+ sb.append(':').append(infoTimestamp);
+ }
+
+ sb.append(')');
+
+ if (!UNAVAILABLE.equals(infoClassloader)) {
+ sb.append('@').append(infoClassloader);
+ }
+
+ return sb.toString();
+ }
+
+
+ /**
+ * Loads version information for a list of packages.
+ *
+ * @param pckgs the packages for which to load version info
+ * @param clsldr the classloader to load from, or
+ * <code>null</code> for the thread context classloader
+ *
+ * @return the version information for all packages found,
+ * never <code>null</code>
+ */
+ public static VersionInfo[] loadVersionInfo(final String[] pckgs,
+ final ClassLoader clsldr) {
+ Args.notNull(pckgs, "Package identifier array");
+ final List<VersionInfo> vil = new ArrayList<VersionInfo>(pckgs.length);
+ for (final String pckg : pckgs) {
+ final VersionInfo vi = loadVersionInfo(pckg, clsldr);
+ if (vi != null) {
+ vil.add(vi);
+ }
+ }
+
+ return vil.toArray(new VersionInfo[vil.size()]);
+ }
+
+
+ /**
+ * Loads version information for a package.
+ *
+ * @param pckg the package for which to load version information,
+ * for example "ch.boye.httpclientandroidlib".
+ * The package name should NOT end with a dot.
+ * @param clsldr the classloader to load from, or
+ * <code>null</code> for the thread context classloader
+ *
+ * @return the version information for the argument package, or
+ * <code>null</code> if not available
+ */
+ public static VersionInfo loadVersionInfo(final String pckg,
+ final ClassLoader clsldr) {
+ Args.notNull(pckg, "Package identifier");
+ final ClassLoader cl = clsldr != null ? clsldr : Thread.currentThread().getContextClassLoader();
+
+ Properties vip = null; // version info properties, if available
+ try {
+ // ch.boye.httpclientandroidlib becomes
+ // org/apache/http/version.properties
+ final InputStream is = cl.getResourceAsStream
+ (pckg.replace('.', '/') + "/" + VERSION_PROPERTY_FILE);
+ if (is != null) {
+ try {
+ final Properties props = new Properties();
+ props.load(is);
+ vip = props;
+ } finally {
+ is.close();
+ }
+ }
+ } catch (final IOException ex) {
+ // shamelessly munch this exception
+ }
+
+ VersionInfo result = null;
+ if (vip != null) {
+ result = fromMap(pckg, vip, cl);
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Instantiates version information from properties.
+ *
+ * @param pckg the package for the version information
+ * @param info the map from string keys to string values,
+ * for example {@link java.util.Properties}
+ * @param clsldr the classloader, or <code>null</code>
+ *
+ * @return the version information
+ */
+ protected static VersionInfo fromMap(final String pckg, final Map<?, ?> info,
+ final ClassLoader clsldr) {
+ Args.notNull(pckg, "Package identifier");
+ String module = null;
+ String release = null;
+ String timestamp = null;
+
+ if (info != null) {
+ module = (String) info.get(PROPERTY_MODULE);
+ if ((module != null) && (module.length() < 1)) {
+ module = null;
+ }
+
+ release = (String) info.get(PROPERTY_RELEASE);
+ if ((release != null) && ((release.length() < 1) ||
+ (release.equals("${pom.version}")))) {
+ release = null;
+ }
+
+ timestamp = (String) info.get(PROPERTY_TIMESTAMP);
+ if ((timestamp != null) &&
+ ((timestamp.length() < 1) ||
+ (timestamp.equals("${mvn.timestamp}")))
+ ) {
+ timestamp = null;
+ }
+ } // if info
+
+ String clsldrstr = null;
+ if (clsldr != null) {
+ clsldrstr = clsldr.toString();
+ }
+
+ return new VersionInfo(pckg, module, release, timestamp, clsldrstr);
+ }
+
+ /**
+ * Sets the user agent to {@code "<name>/<release> (Java 1.5 minimum; Java/<java.version>)"}.
+ * <p/>
+ * For example:
+ * <pre>"Apache-HttpClient/4.3 (Java 1.5 minimum; Java/1.6.0_35)"</pre>
+ *
+ * @param name the component name, like "Apache-HttpClient".
+ * @param pkg
+ * the package for which to load version information, for example "ch.boye.httpclientandroidlib". The package name
+ * should NOT end with a dot.
+ * @param cls
+ * the class' class loader to load from, or <code>null</code> for the thread context class loader
+ * @since 4.3
+ */
+ public static String getUserAgent(final String name, final String pkg, final Class<?> cls) {
+ // determine the release version from packaged version info
+ final VersionInfo vi = VersionInfo.loadVersionInfo(pkg, cls.getClassLoader());
+ final String release = (vi != null) ? vi.getRelease() : VersionInfo.UNAVAILABLE;
+ final String javaVersion = System.getProperty("java.version");
+ return name + "/" + release + " (Java 1.5 minimum; Java/" + javaVersion + ")";
+ }
+
+} // class VersionInfo
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/package-info.java
new file mode 100644
index 000000000..8cc0a0f2d
--- /dev/null
+++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/util/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/**
+ * Core utility classes.
+ */
+package ch.boye.httpclientandroidlib.util;