public final class HttpConversationManager
extends java.lang.Object
setDefault(HttpConversationManager)
.
IHttpConversation
object using create(URL)
, is as follows:
IRequestListener
supplied to the IHttpConversation
object. This produces the final set of
request headers and the request body.IHttpConversation
object. These filters have
the power to cancel the processing and to actually restart the entire flow in case it's required.IResponseListener
supplied to the IHttpConversation
object.
The above flow is submitted as a single continuous processing unit to the executor defined by setExecutor(Executor)
.
IConnectionConfigurationListener
interface. The
implementations are to be provided by the client of this library. These get executed just before the actual HTTP/HTTPS connection is built.
For simplicity, instances of IManagerConfigurator
might be used to configure a conversation manager to a typical, high-level use case.
Instances of the configurer are usually supplied by
additional libraries which are intended to support special use cases (for example: SAML2, OAuth2, etc..).
The configuration of the manager is considered closed the first time the create(URL)
method is invoked. After that all configuration
methods throw IllegalStateException
.
IContext
) using which state
information can be preserved and exchanged:
IHttpConversation
. This allows filters and listeners to communicate with each other within
the boundaries of a single request/response
exchange.getName()
and IHttpConversation.getName()
, respectively.
These names need not be unique and serves nothing
else just identification purposes. Clients of this library can name managers and conversations to be able to categorize certain network
interactions in an easy way. For example, an application can
give similar names to conversations executed from a particular screen to easily identify them when reading the responses. This can make it easier
to find out where on the User Interface the results
need to be shown.
SAPCookieManager
for cookie handling. That means the library sets it as default cookie handler. Clients should pay
attention to this
in case a custom cookie handler is used via the same mechanism. If there is already a default CookieHandler
set the library will copy every
cookie from it to
SAPCookieManager
. This is done when a new instance is created. In order to turn off this behaviour, invoke the SAPCookieManager.setForceOverride(boolean)
method with a false argument.
Refer to the documentation of SAPCookieManager
for the details.
setSSLSocketFactoryListener
, the addTrustManager
and the addKeyManager
methods. The latter ones can be used to add independent trust and key
managers which will then be exchanged for an
SSLSocketFactory
via the configured ISSLSocketFactoryListener
. The main purpose of this pattern is that specifying trust and key
managers is independent from the process of making a
factory out of these. The default SSL socket factory listener initializes a single SSLContext
using the 'SSL' protocol.
The redirects occuring during an HTTP conversation are handled manually. This means that the following of redirects is turned off on the underlying
HttpURLConnection
using
HttpURLConnection.setInstanceFollowRedirects(boolean)
. Furthermore, this manager is capable of consulting a whitelist whether the given
redirect should be allowed or not. In case a non-null
instance of RedirectWhitelist
is set using setRedirectWhitelist(RedirectWhitelist)
and the redirect URL is found to be invalid
then the conversation fails with an
InvalidRedirectUrlException
(which is a subclass of IOException
). To detect this, look for this type of exception in the
ICommunicationErrorListener.onCommunicationError(IOException)
method.
By default, no redirect whitelist is set which means that the conversation manager allows all redirects unconditionally.
create(URL)
can be safely done by multiple
threads. The actual conversations are executed using the configured executor set via setExecutor(Executor)
which is the one that actually
decides where and how to execute the entire
conversation flow.
addObserver
method. Subinterfaces of IObserver
defined within the
com.sap.smp.client.httpc.observers
package have built-in support in the conversation manager. Further, user-defined observers can also be
added but they must be invoked by corresponding
request and response filters/listeners. For this purpose, the collection of registered observers can be queried using the IBaseEvent.getObserversByType(Class)
method, making the collection
available for all filters and listeners via their event parameters.
copy()
method can be used for
this purpose.
Modifier and Type | Class and Description |
---|---|
static class |
HttpConversationManager.Setting
Enumeration of the possible settings of a
HttpConversationManager . |
Modifier and Type | Field and Description |
---|---|
static int |
DEFAULT_MAX_RESTARTS
The default number of allowed flow restarts.
|
Constructor and Description |
---|
HttpConversationManager(android.content.Context context)
Creates a new conversation manager.
|
Modifier and Type | Method and Description |
---|---|
HttpConversationManager |
addFilter(IRequestFilter filter)
Appends the specified request filter to the end of the chain.
|
HttpConversationManager |
addFilter(IResponseFilter filter)
Appends the specified response filter to the end of the chain.
|
HttpConversationManager |
addFilterIfMissing(IRequestFilter filter)
Convenience method to add a request filter only if it has not been added yet, as of it's descriptor.
|
HttpConversationManager |
addFilterIfMissing(IResponseFilter filter)
Convenience method to add a response filter only if it has not been added yet, as of it's descriptor.
|
HttpConversationManager |
addKeyManager(javax.net.ssl.X509KeyManager keyManager)
Adds a new key manager to be used during SSL handshake.
|
HttpConversationManager |
addObserver(IObserver observer)
Adds a new observer to this manager which will be active only for conversations that are started after this method is called.
|
HttpConversationManager |
addTrustManager(javax.net.ssl.X509TrustManager trustManager)
Adds a new trust manager to be used during SSL handshake.
|
void |
closeSettings(HttpConversationManager.Setting... settings)
Closes the specified settings.
|
HttpConversationManager |
configuredBy(IManagerConfigurator configurator)
Marks this manager using the specified configurator object.
|
HttpConversationManager |
copy()
Creates a copy of this manager.
|
IHttpConversation |
create(android.net.Uri uri)
Convenience overload of
create(URL) that uses the Uri class instead. |
IHttpConversation |
create(java.net.URL url)
Creates a new HTTP conversation using the configuration set in this manager.
|
static HttpConversationManager |
getDefault()
Returns the default conversation manager.
|
ITextBasedResponseDetector |
getDefaultTextBasedResponseDetector()
Returns the configured text-based response detector.
|
static ITextBasedResponseDetector |
getInitialDetector()
Returns the initial detector to be set for a conversation manager in case one wishes to reset the default.
|
java.lang.String |
getName()
Returns the name of this manager.
|
RedirectWhitelist |
getRedirectWhitelist()
Returns the configured redirect whitelist.
|
java.util.List<IRequestFilter> |
getRequestFilterChain()
Returns a list of
IRequestFilter . |
java.util.List<IResponseFilter> |
getResponseFilterChain()
Returns a list of
IResponseFilter . |
ISSLSocketFactoryListener |
getSSLSocketFactoryListener()
Returns the socket factory listener currently in use.
|
boolean |
hasRequestFilter(java.lang.Object descriptor)
Tests whether this manager has a request filter added which has a descriptor that
equals to the specified one. |
boolean |
hasResponseFilter(java.lang.Object descriptor)
Tests whether this manager has a response filter added which has a descriptor that
equals to the specified one. |
boolean |
isConfiguredBy(IManagerConfigurator configurator)
Checks whether this manager has been marked by the specified configurator, as of the
Object.equals(Object) method. |
static void |
setDefault(HttpConversationManager manager)
Sets the default conversation manager.
|
HttpConversationManager |
setDefaultFlowListener(IConversationFlowListener listener)
Sets the default flow listener newly created
IHttpConversation will use. |
HttpConversationManager |
setDefaultMaximumRestarts(int maximumRestarts)
Sets the default value for the maximum number of flow restarts allowed.
|
HttpConversationManager |
setDefaultTextBasedResponseDetector(ITextBasedResponseDetector detector)
Sets the default detector that can be used to detect text-based responses to allow response filters and response listeners to read the response
using a
Reader instead of just an
InputStream . |
HttpConversationManager |
setExecutor(java.util.concurrent.Executor executor)
Sets the executor to use when executing the flow.
|
HttpConversationManager |
setHostnameVerifierListener(IConnectionConfigurationListener<javax.net.ssl.HostnameVerifier> listener)
Sets the hostname verifier listener.
|
HttpConversationManager |
setName(java.lang.String name)
Sets the name of this manager.
|
HttpConversationManager |
setProxyProviderListener(IConnectionConfigurationListener<java.net.Proxy> listener)
Sets the proxy provider listener.
|
HttpConversationManager |
setRedirectWhitelist(RedirectWhitelist redirectWhitelist)
Sets the redirect whitelist.
|
HttpConversationManager |
setSSLSocketFactoryListener(ISSLSocketFactoryListener listener)
Sets the SSL socket factory listener.
|
public static final int DEFAULT_MAX_RESTARTS
public HttpConversationManager(android.content.Context context)
context
- a context object, must be non-nullpublic static HttpConversationManager getDefault()
public static void setDefault(HttpConversationManager manager)
manager
- the manager, can be nullpublic static ITextBasedResponseDetector getInitialDetector()
public java.lang.String getName()
public HttpConversationManager setName(java.lang.String name)
IContext
objects accessible from IBaseEvent
s.name
- the name, can be nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closedpublic HttpConversationManager setDefaultMaximumRestarts(int maximumRestarts)
DEFAULT_MAX_RESTARTS
. For
further details, see the
IHttpConversation.setMaximumRestarts(int)
method. Newly created conversations will use this value by default.maximumRestarts
- the maximum number of restartsjava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closedpublic RedirectWhitelist getRedirectWhitelist()
public HttpConversationManager setRedirectWhitelist(RedirectWhitelist redirectWhitelist)
redirectWhitelist
- the redirect whitelist, can be nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closedpublic HttpConversationManager setExecutor(java.util.concurrent.Executor executor)
Note that care must be taken when setting a synchronous executor as this way the flow might be executed on the UI thread. Considering that
request/response filters might perform UI interaction
this can lead to a deadlock! It's strongly advised that any custom executor set offloads all processing to worker threads (obtained from a
thread pool, for example). However, if the manager
itself is guaranteed to be used from background threads then utilizing a synchronous executor is the way to go. In this case the SynchronousExecutor
utility singleton can be used.
executor
- the executor, can be nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closed or in case the HttpConversationManager.Setting.EXECUTOR
setting has been closed
using closeSettings()
public HttpConversationManager addFilter(IRequestFilter filter)
filter
- the filter, must be non-nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closedpublic HttpConversationManager addFilterIfMissing(IRequestFilter filter)
if (!hasRequestFilter(filter.getDescriptor())) addFilter(filter);
filter
- the filter, must be non-nullpublic boolean hasRequestFilter(java.lang.Object descriptor)
equals
to the specified one.descriptor
- the descriptor, must be non-nullpublic HttpConversationManager addFilter(IResponseFilter filter)
filter
- the filter, must be non-nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closedpublic HttpConversationManager addFilterIfMissing(IResponseFilter filter)
if (!hasResponseFilter(filter.getDescriptor())) addFilter(filter);
filter
- the filter, must be non-nullpublic boolean hasResponseFilter(java.lang.Object descriptor)
equals
to the specified one.descriptor
- the descriptor, must be non-nullpublic HttpConversationManager setDefaultFlowListener(IConversationFlowListener listener)
IHttpConversation
will use.listener
- the listener, can be nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closedpublic HttpConversationManager setHostnameVerifierListener(IConnectionConfigurationListener<javax.net.ssl.HostnameVerifier> listener)
listener
- the listener, can be nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closed or in case the HttpConversationManager.Setting.HOSTNAME_VERIFIER
setting has been
closed using closeSettings()
public ISSLSocketFactoryListener getSSLSocketFactoryListener()
public HttpConversationManager setSSLSocketFactoryListener(ISSLSocketFactoryListener listener)
Note that the default listener is actually an instance of DefaultSSLSocketFactoryListener
.
Application-specific trust and key managers can be added using the addTrustManager(X509TrustManager)
and addKeyManager(X509KeyManager)
APIs.
listener
- the listener, can be null (which resets the default)java.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closed or in case the HttpConversationManager.Setting.SSL_SOCKET_FACTORY
setting has been
closed using closeSettings()
public HttpConversationManager addTrustManager(javax.net.ssl.X509TrustManager trustManager)
trustManager
- a trust manager, must be non-nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closed or in case the HttpConversationManager.Setting.TRUST_MANAGER
setting has been
closed using closeSettings()
public HttpConversationManager addKeyManager(javax.net.ssl.X509KeyManager keyManager)
keyManager
- a key manager, must be non-nulljava.lang.IllegalStateException
- in case the create(URL)
method has been called beforehand and the configuration of this manager is
closed or in case the HttpConversationManager.Setting.KEY_MANAGER
setting has been closed
using closeSettings()
public HttpConversationManager setProxyProviderListener(IConnectionConfigurationListener<java.net.Proxy> listener)
listener
- the listener, can be nulljava.lang.IllegalStateException
- in case the (@link create(URL)
method has been called beforehand and the configuration of this manager
is closed or in case the HttpConversationManager.Setting.PROXY_PROVIDER
setting has
been closed using closeSettings()
public ITextBasedResponseDetector getDefaultTextBasedResponseDetector()
public HttpConversationManager setDefaultTextBasedResponseDetector(ITextBasedResponseDetector detector)
Reader
instead of just an
InputStream
. The value set using this method is going to be inherited by IHttpConversation
objects created using this manager.
Initially, the detector set for this conversation manager is the one obtained using getInitialDetector()
.
detector
- the detector to set, can be nulljava.lang.IllegalStateException
- in case the (@link create(URL)
method has been called beforehand and the configuration of this manager
is closed or in case the HttpConversationManager.Setting.RESPONSE_DETECTOR
setting
has been closed using closeSettings()
public HttpConversationManager addObserver(IObserver observer)
observer
- the observer, must be non-nullpublic HttpConversationManager configuredBy(IManagerConfigurator configurator)
IManagerConfigurator
implementations whose
configure
method is not idempotent. Such configurators usually invoke isConfiguredBy(IManagerConfigurator)
on the
manager to check whether configuration is to be done or not.
Internally, this class stores weak references to configurators (thereby representing a mark).
configurator
- the configurator to mark this manager with, must be non-nullpublic boolean isConfiguredBy(IManagerConfigurator configurator)
Object.equals(Object)
method.configurator
- the configurator, must be non-nullpublic IHttpConversation create(java.net.URL url)
There's no need to include request parameters in the URL as it can be done afterwards using the IHttpConversation.addParameter(String,
String)
method.
url
- the endpoint URL, must be non-nulljava.lang.IllegalArgumentException
- in case the URL scheme is not supportedpublic IHttpConversation create(android.net.Uri uri)
create(URL)
that uses the Uri
class instead.uri
- the endpoint URL, represented as a Uri
, must be non-nulljava.lang.IllegalArgumentException
- if the URL is malformed or the scheme is unsupportedpublic HttpConversationManager copy()
The main purpose of this method is to allow for the creation of a new manager based on the settings of an existing one, thereby replicating it's configuration in another one. The returned manager is configurable as it was not yet used to create conversations.
public java.util.List<IRequestFilter> getRequestFilterChain()
IRequestFilter
. The returned list of filters are modifiable by the caller.public java.util.List<IResponseFilter> getResponseFilterChain()
IResponseFilter
. The returned list of filters are modifiable by the caller.public void closeSettings(HttpConversationManager.Setting... settings)
Closing an already closed setting has no effect.
The main purpose of this method is to support IManagerConfigurator
implementations to close of certain settings from external
modifications. A good example is a configurator which adds
a custom SSL socket factory listener that's collaborating with a series of filters added by the same configurator. Allowing one to set a new
SSL socket factory listener would break the
functionality. By closing off a series of settings it becomes possible to detect conflicting configurations and an improperly configured
conversation manager.
settings
- the array of settings, can be null