Propagate updates of default header fields of the HttpDataSource.BaseFactory to HttpDataSource instances.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=149780233
This commit is contained in:
parent
952bde700b
commit
aede0f894d
@ -118,7 +118,8 @@ public final class CronetDataSourceTest {
|
||||
TEST_CONNECT_TIMEOUT_MS,
|
||||
TEST_READ_TIMEOUT_MS,
|
||||
true, // resetTimeoutOnRedirects
|
||||
mockClock));
|
||||
mockClock,
|
||||
null));
|
||||
when(mockContentTypePredicate.evaluate(anyString())).thenReturn(true);
|
||||
when(mockCronetEngine.newUrlRequestBuilder(
|
||||
anyString(), any(UrlRequest.Callback.class), any(Executor.class)))
|
||||
|
@ -32,7 +32,6 @@ import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@ -98,7 +97,8 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
|
||||
private final int connectTimeoutMs;
|
||||
private final int readTimeoutMs;
|
||||
private final boolean resetTimeoutOnRedirects;
|
||||
private final Map<String, String> requestProperties;
|
||||
private final RequestProperties defaultRequestProperties;
|
||||
private final RequestProperties requestProperties;
|
||||
private final ConditionVariable operation;
|
||||
private final Clock clock;
|
||||
|
||||
@ -136,7 +136,7 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
|
||||
public CronetDataSource(CronetEngine cronetEngine, Executor executor,
|
||||
Predicate<String> contentTypePredicate, TransferListener<? super CronetDataSource> listener) {
|
||||
this(cronetEngine, executor, contentTypePredicate, listener, DEFAULT_CONNECT_TIMEOUT_MILLIS,
|
||||
DEFAULT_READ_TIMEOUT_MILLIS, false);
|
||||
DEFAULT_READ_TIMEOUT_MILLIS, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,17 +149,20 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
|
||||
* @param connectTimeoutMs The connection timeout, in milliseconds.
|
||||
* @param readTimeoutMs The read timeout, in milliseconds.
|
||||
* @param resetTimeoutOnRedirects Whether the connect timeout is reset when a redirect occurs.
|
||||
* @param defaultRequestProperties The default request properties to be used.
|
||||
*/
|
||||
public CronetDataSource(CronetEngine cronetEngine, Executor executor,
|
||||
Predicate<String> contentTypePredicate, TransferListener<? super CronetDataSource> listener,
|
||||
int connectTimeoutMs, int readTimeoutMs, boolean resetTimeoutOnRedirects) {
|
||||
int connectTimeoutMs, int readTimeoutMs, boolean resetTimeoutOnRedirects,
|
||||
RequestProperties defaultRequestProperties) {
|
||||
this(cronetEngine, executor, contentTypePredicate, listener, connectTimeoutMs,
|
||||
readTimeoutMs, resetTimeoutOnRedirects, new SystemClock());
|
||||
readTimeoutMs, resetTimeoutOnRedirects, new SystemClock(), defaultRequestProperties);
|
||||
}
|
||||
|
||||
/* package */ CronetDataSource(CronetEngine cronetEngine, Executor executor,
|
||||
Predicate<String> contentTypePredicate, TransferListener<? super CronetDataSource> listener,
|
||||
int connectTimeoutMs, int readTimeoutMs, boolean resetTimeoutOnRedirects, Clock clock) {
|
||||
int connectTimeoutMs, int readTimeoutMs, boolean resetTimeoutOnRedirects, Clock clock,
|
||||
RequestProperties defaultRequestProperties) {
|
||||
this.cronetEngine = Assertions.checkNotNull(cronetEngine);
|
||||
this.executor = Assertions.checkNotNull(executor);
|
||||
this.contentTypePredicate = contentTypePredicate;
|
||||
@ -168,7 +171,8 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
|
||||
this.readTimeoutMs = readTimeoutMs;
|
||||
this.resetTimeoutOnRedirects = resetTimeoutOnRedirects;
|
||||
this.clock = Assertions.checkNotNull(clock);
|
||||
requestProperties = new HashMap<>();
|
||||
this.defaultRequestProperties = defaultRequestProperties;
|
||||
requestProperties = new RequestProperties();
|
||||
operation = new ConditionVariable();
|
||||
}
|
||||
|
||||
@ -176,23 +180,17 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
|
||||
|
||||
@Override
|
||||
public void setRequestProperty(String name, String value) {
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.put(name, value);
|
||||
}
|
||||
requestProperties.set(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRequestProperty(String name) {
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllRequestProperties() {
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.clear();
|
||||
}
|
||||
requestProperties.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -421,16 +419,24 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
|
||||
UrlRequest.Builder requestBuilder = cronetEngine.newUrlRequestBuilder(dataSpec.uri.toString(),
|
||||
this, executor);
|
||||
// Set the headers.
|
||||
synchronized (requestProperties) {
|
||||
if (dataSpec.postBody != null && dataSpec.postBody.length != 0
|
||||
&& !requestProperties.containsKey(CONTENT_TYPE)) {
|
||||
throw new OpenException("POST request with non-empty body must set Content-Type", dataSpec,
|
||||
Status.IDLE);
|
||||
}
|
||||
for (Entry<String, String> headerEntry : requestProperties.entrySet()) {
|
||||
requestBuilder.addHeader(headerEntry.getKey(), headerEntry.getValue());
|
||||
boolean isContentTypeHeaderSet = false;
|
||||
if (defaultRequestProperties != null) {
|
||||
for (Entry<String, String> headerEntry : defaultRequestProperties.getSnapshot().entrySet()) {
|
||||
String key = headerEntry.getKey();
|
||||
isContentTypeHeaderSet = isContentTypeHeaderSet || CONTENT_TYPE.equals(key);
|
||||
requestBuilder.addHeader(key, headerEntry.getValue());
|
||||
}
|
||||
}
|
||||
Map<String, String> requestPropertiesSnapshot = requestProperties.getSnapshot();
|
||||
for (Entry<String, String> headerEntry : requestPropertiesSnapshot.entrySet()) {
|
||||
String key = headerEntry.getKey();
|
||||
isContentTypeHeaderSet = isContentTypeHeaderSet || CONTENT_TYPE.equals(key);
|
||||
requestBuilder.addHeader(key, headerEntry.getValue());
|
||||
}
|
||||
if (dataSpec.postBody != null && dataSpec.postBody.length != 0 && !isContentTypeHeaderSet) {
|
||||
throw new OpenException("POST request with non-empty body must set Content-Type", dataSpec,
|
||||
Status.IDLE);
|
||||
}
|
||||
// Set the Range header.
|
||||
if (currentDataSpec.position != 0 || currentDataSpec.length != C.LENGTH_UNSET) {
|
||||
StringBuilder rangeValue = new StringBuilder();
|
||||
|
@ -16,6 +16,7 @@
|
||||
package com.google.android.exoplayer2.ext.cronet;
|
||||
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource.Factory;
|
||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||
@ -68,9 +69,10 @@ public final class CronetDataSourceFactory extends BaseFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CronetDataSource createDataSourceInternal() {
|
||||
protected CronetDataSource createDataSourceInternal(HttpDataSource.RequestProperties
|
||||
defaultRequestProperties) {
|
||||
return new CronetDataSource(cronetEngine, executor, contentTypePredicate, transferListener,
|
||||
connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects);
|
||||
connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects, null, defaultRequestProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@ -51,7 +50,8 @@ public class OkHttpDataSource implements HttpDataSource {
|
||||
private final Predicate<String> contentTypePredicate;
|
||||
private final TransferListener<? super OkHttpDataSource> listener;
|
||||
private final CacheControl cacheControl;
|
||||
private final HashMap<String, String> requestProperties;
|
||||
private final RequestProperties defaultRequestProperties;
|
||||
private final RequestProperties requestProperties;
|
||||
|
||||
private DataSpec dataSpec;
|
||||
private Response response;
|
||||
@ -87,7 +87,7 @@ public class OkHttpDataSource implements HttpDataSource {
|
||||
*/
|
||||
public OkHttpDataSource(Call.Factory callFactory, String userAgent,
|
||||
Predicate<String> contentTypePredicate, TransferListener<? super OkHttpDataSource> listener) {
|
||||
this(callFactory, userAgent, contentTypePredicate, listener, null);
|
||||
this(callFactory, userAgent, contentTypePredicate, listener, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,16 +99,19 @@ public class OkHttpDataSource implements HttpDataSource {
|
||||
* {@link #open(DataSpec)}.
|
||||
* @param listener An optional listener.
|
||||
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
|
||||
* @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to
|
||||
* the server as HTTP headers on every request.
|
||||
*/
|
||||
public OkHttpDataSource(Call.Factory callFactory, String userAgent,
|
||||
Predicate<String> contentTypePredicate, TransferListener<? super OkHttpDataSource> listener,
|
||||
CacheControl cacheControl) {
|
||||
CacheControl cacheControl, RequestProperties defaultRequestProperties) {
|
||||
this.callFactory = Assertions.checkNotNull(callFactory);
|
||||
this.userAgent = Assertions.checkNotEmpty(userAgent);
|
||||
this.contentTypePredicate = contentTypePredicate;
|
||||
this.listener = listener;
|
||||
this.cacheControl = cacheControl;
|
||||
this.requestProperties = new HashMap<>();
|
||||
this.defaultRequestProperties = defaultRequestProperties;
|
||||
this.requestProperties = new RequestProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -125,24 +128,18 @@ public class OkHttpDataSource implements HttpDataSource {
|
||||
public void setRequestProperty(String name, String value) {
|
||||
Assertions.checkNotNull(name);
|
||||
Assertions.checkNotNull(value);
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.put(name, value);
|
||||
}
|
||||
requestProperties.set(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRequestProperty(String name) {
|
||||
Assertions.checkNotNull(name);
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllRequestProperties() {
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.clear();
|
||||
}
|
||||
requestProperties.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -268,11 +265,14 @@ public class OkHttpDataSource implements HttpDataSource {
|
||||
if (cacheControl != null) {
|
||||
builder.cacheControl(cacheControl);
|
||||
}
|
||||
synchronized (requestProperties) {
|
||||
for (Map.Entry<String, String> property : requestProperties.entrySet()) {
|
||||
builder.addHeader(property.getKey(), property.getValue());
|
||||
if (defaultRequestProperties != null) {
|
||||
for (Map.Entry<String, String> property : defaultRequestProperties.getSnapshot().entrySet()) {
|
||||
builder.header(property.getKey(), property.getValue());
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, String> property : requestProperties.getSnapshot().entrySet()) {
|
||||
builder.header(property.getKey(), property.getValue());
|
||||
}
|
||||
if (!(position == 0 && length == C.LENGTH_UNSET)) {
|
||||
String rangeRequest = "bytes=" + position + "-";
|
||||
if (length != C.LENGTH_UNSET) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
package com.google.android.exoplayer2.ext.okhttp;
|
||||
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource.Factory;
|
||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||
@ -59,8 +60,10 @@ public final class OkHttpDataSourceFactory extends BaseFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OkHttpDataSource createDataSourceInternal() {
|
||||
return new OkHttpDataSource(callFactory, userAgent, null, listener, cacheControl);
|
||||
protected OkHttpDataSource createDataSourceInternal(
|
||||
HttpDataSource.RequestProperties defaultRequestProperties) {
|
||||
return new OkHttpDataSource(callFactory, userAgent, null, listener, cacheControl,
|
||||
defaultRequestProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public final class DefaultDataSource implements DataSource {
|
||||
boolean allowCrossProtocolRedirects) {
|
||||
this(context, listener,
|
||||
new DefaultHttpDataSource(userAgent, null, listener, connectTimeoutMillis,
|
||||
readTimeoutMillis, allowCrossProtocolRedirects));
|
||||
readTimeoutMillis, allowCrossProtocolRedirects, null));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,6 @@ import java.net.HttpURLConnection;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@ -44,8 +43,8 @@ import java.util.regex.Pattern;
|
||||
* <p>
|
||||
* By default this implementation will not follow cross-protocol redirects (i.e. redirects from
|
||||
* HTTP to HTTPS or vice versa). Cross-protocol redirects can be enabled by using the
|
||||
* {@link #DefaultHttpDataSource(String, Predicate, TransferListener, int, int, boolean)}
|
||||
* constructor and passing {@code true} as the final argument.
|
||||
* {@link #DefaultHttpDataSource(String, Predicate, TransferListener, int, int, boolean,
|
||||
* RequestProperties)} constructor and passing {@code true} as the second last argument.
|
||||
*/
|
||||
public class DefaultHttpDataSource implements HttpDataSource {
|
||||
|
||||
@ -70,7 +69,8 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||
private final int readTimeoutMillis;
|
||||
private final String userAgent;
|
||||
private final Predicate<String> contentTypePredicate;
|
||||
private final HashMap<String, String> requestProperties;
|
||||
private final RequestProperties defaultRequestProperties;
|
||||
private final RequestProperties requestProperties;
|
||||
private final TransferListener<? super DefaultHttpDataSource> listener;
|
||||
|
||||
private DataSpec dataSpec;
|
||||
@ -121,7 +121,8 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate,
|
||||
TransferListener<? super DefaultHttpDataSource> listener, int connectTimeoutMillis,
|
||||
int readTimeoutMillis) {
|
||||
this(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis, false);
|
||||
this(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis, false,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,17 +138,21 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||
* as an infinite timeout. Pass {@link #DEFAULT_READ_TIMEOUT_MILLIS} to use the default value.
|
||||
* @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
|
||||
* to HTTPS and vice versa) are enabled.
|
||||
* @param defaultRequestProperties The default request properties to be sent to the server as
|
||||
* HTTP headers or {@code null} if not required.
|
||||
*/
|
||||
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate,
|
||||
TransferListener<? super DefaultHttpDataSource> listener, int connectTimeoutMillis,
|
||||
int readTimeoutMillis, boolean allowCrossProtocolRedirects) {
|
||||
int readTimeoutMillis, boolean allowCrossProtocolRedirects,
|
||||
RequestProperties defaultRequestProperties) {
|
||||
this.userAgent = Assertions.checkNotEmpty(userAgent);
|
||||
this.contentTypePredicate = contentTypePredicate;
|
||||
this.listener = listener;
|
||||
this.requestProperties = new HashMap<>();
|
||||
this.requestProperties = new RequestProperties();
|
||||
this.connectTimeoutMillis = connectTimeoutMillis;
|
||||
this.readTimeoutMillis = readTimeoutMillis;
|
||||
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
|
||||
this.defaultRequestProperties = defaultRequestProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -164,24 +169,18 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||
public void setRequestProperty(String name, String value) {
|
||||
Assertions.checkNotNull(name);
|
||||
Assertions.checkNotNull(value);
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.put(name, value);
|
||||
}
|
||||
requestProperties.set(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRequestProperty(String name) {
|
||||
Assertions.checkNotNull(name);
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllRequestProperties() {
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.clear();
|
||||
}
|
||||
requestProperties.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -394,11 +393,14 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setConnectTimeout(connectTimeoutMillis);
|
||||
connection.setReadTimeout(readTimeoutMillis);
|
||||
synchronized (requestProperties) {
|
||||
for (Map.Entry<String, String> property : requestProperties.entrySet()) {
|
||||
if (defaultRequestProperties != null) {
|
||||
for (Map.Entry<String, String> property : defaultRequestProperties.getSnapshot().entrySet()) {
|
||||
connection.setRequestProperty(property.getKey(), property.getValue());
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, String> property : requestProperties.getSnapshot().entrySet()) {
|
||||
connection.setRequestProperty(property.getKey(), property.getValue());
|
||||
}
|
||||
if (!(position == 0 && length == C.LENGTH_UNSET)) {
|
||||
String rangeRequest = "bytes=" + position + "-";
|
||||
if (length != C.LENGTH_UNSET) {
|
||||
|
@ -76,9 +76,10 @@ public final class DefaultHttpDataSourceFactory extends BaseFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultHttpDataSource createDataSourceInternal() {
|
||||
protected DefaultHttpDataSource createDataSourceInternal(
|
||||
HttpDataSource.RequestProperties defaultRequestProperties) {
|
||||
return new DefaultHttpDataSource(userAgent, null, listener, connectTimeoutMillis,
|
||||
readTimeoutMillis, allowCrossProtocolRedirects);
|
||||
readTimeoutMillis, allowCrossProtocolRedirects, getDefaultRequestProperties());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,12 +17,12 @@ package com.google.android.exoplayer2.upstream;
|
||||
|
||||
import android.support.annotation.IntDef;
|
||||
import android.text.TextUtils;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Predicate;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -41,84 +41,173 @@ public interface HttpDataSource extends DataSource {
|
||||
HttpDataSource createDataSource();
|
||||
|
||||
/**
|
||||
* Sets a default request header for {@link HttpDataSource} instances subsequently created by
|
||||
* the factory. Previously created instances are not affected.
|
||||
* Gets the default request properties used by all {@link HttpDataSource}s created by the
|
||||
* factory. Changes to the properties will be reflected in any future requests made by
|
||||
* {@link HttpDataSource}s created by the factory.
|
||||
*
|
||||
* @return The default request properties of the factory.
|
||||
*/
|
||||
RequestProperties getDefaultRequestProperties();
|
||||
|
||||
/**
|
||||
* Sets a default request header for {@link HttpDataSource} instances created by the factory.
|
||||
*
|
||||
* @deprecated Use {@link #getDefaultRequestProperties} instead.
|
||||
* @param name The name of the header field.
|
||||
* @param value The value of the field.
|
||||
*/
|
||||
@Deprecated
|
||||
void setDefaultRequestProperty(String name, String value);
|
||||
|
||||
/**
|
||||
* Clears a default request header for {@link HttpDataSource} instances subsequently created by
|
||||
* the factory. Previously created instances are not affected.
|
||||
* Clears a default request header for {@link HttpDataSource} instances created by the factory.
|
||||
*
|
||||
* @deprecated Use {@link #getDefaultRequestProperties} instead.
|
||||
* @param name The name of the header field.
|
||||
*/
|
||||
@Deprecated
|
||||
void clearDefaultRequestProperty(String name);
|
||||
|
||||
/**
|
||||
* Clears all default request header for all {@link HttpDataSource} instances subsequently
|
||||
* created by the factory. Previously created instances are not affected.
|
||||
* Clears all default request headers for all {@link HttpDataSource} instances created by the
|
||||
* factory.
|
||||
*
|
||||
* @deprecated Use {@link #getDefaultRequestProperties} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
void clearAllDefaultRequestProperties();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores HTTP request properties (aka HTTP headers) and provides methods to modify the headers
|
||||
* in a thread safe way to avoid the potential of creating snapshots of an inconsistent or
|
||||
* unintended state.
|
||||
*/
|
||||
final class RequestProperties {
|
||||
|
||||
private final Map<String, String> requestProperties;
|
||||
private Map<String, String> requestPropertiesSnapshot;
|
||||
|
||||
public RequestProperties() {
|
||||
requestProperties = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified property {@code value} for the specified {@code name}. If a property for
|
||||
* this name previously existed, the old value is replaced by the specified value.
|
||||
*
|
||||
* @param name The name of the request property.
|
||||
* @param value The value of the request property.
|
||||
*/
|
||||
public synchronized void set(String name, String value) {
|
||||
requestPropertiesSnapshot = null;
|
||||
requestProperties.put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keys and values contained in the map. If a property previously existed, the old
|
||||
* value is replaced by the specified value. If a property previously existed and is not in the
|
||||
* map, the property is left unchanged.
|
||||
*
|
||||
* @param properties The request properties.
|
||||
*/
|
||||
public synchronized void set(Map<String, String> properties) {
|
||||
requestPropertiesSnapshot = null;
|
||||
requestProperties.putAll(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all properties previously existing and sets the keys and values of the map.
|
||||
*
|
||||
* @param properties The request properties.
|
||||
*/
|
||||
public synchronized void clearAndSet(Map<String, String> properties) {
|
||||
requestPropertiesSnapshot = null;
|
||||
requestProperties.clear();
|
||||
requestProperties.putAll(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a request property by name.
|
||||
*
|
||||
* @param name The name of the request property to remove.
|
||||
*/
|
||||
public synchronized void remove(String name) {
|
||||
requestPropertiesSnapshot = null;
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all request properties.
|
||||
*/
|
||||
public synchronized void clear() {
|
||||
requestPropertiesSnapshot = null;
|
||||
requestProperties.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a snapshot of the request properties.
|
||||
*
|
||||
* @return A snapshot of the request properties.
|
||||
*/
|
||||
public synchronized Map<String, String> getSnapshot() {
|
||||
if (requestPropertiesSnapshot == null) {
|
||||
requestPropertiesSnapshot = Collections.unmodifiableMap(new HashMap<>(requestProperties));
|
||||
}
|
||||
return requestPropertiesSnapshot;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Base implementation of {@link Factory} that sets default request properties.
|
||||
*/
|
||||
abstract class BaseFactory implements Factory {
|
||||
|
||||
private final HashMap<String, String> requestProperties;
|
||||
private final RequestProperties defaultRequestProperties;
|
||||
|
||||
public BaseFactory() {
|
||||
requestProperties = new HashMap<>();
|
||||
defaultRequestProperties = new RequestProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final HttpDataSource createDataSource() {
|
||||
HttpDataSource dataSource = createDataSourceInternal();
|
||||
synchronized (requestProperties) {
|
||||
for (Map.Entry<String, String> property : requestProperties.entrySet()) {
|
||||
dataSource.setRequestProperty(property.getKey(), property.getValue());
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
return createDataSourceInternal(defaultRequestProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestProperties getDefaultRequestProperties() {
|
||||
return defaultRequestProperties;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public final void setDefaultRequestProperty(String name, String value) {
|
||||
Assertions.checkNotNull(name);
|
||||
Assertions.checkNotNull(value);
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.put(name, value);
|
||||
}
|
||||
defaultRequestProperties.set(name, value);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public final void clearDefaultRequestProperty(String name) {
|
||||
Assertions.checkNotNull(name);
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.remove(name);
|
||||
}
|
||||
defaultRequestProperties.remove(name);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public final void clearAllDefaultRequestProperties() {
|
||||
synchronized (requestProperties) {
|
||||
requestProperties.clear();
|
||||
}
|
||||
defaultRequestProperties.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #createDataSource()} to create a {@link HttpDataSource} instance without
|
||||
* default request properties set. Default request properties will be set by
|
||||
* {@link #createDataSource()} before the instance is returned.
|
||||
* Called by {@link #createDataSource()} to create a {@link HttpDataSource} instance.
|
||||
*
|
||||
* @return A {@link HttpDataSource} instance without default request properties set.
|
||||
* @param defaultRequestProperties The default {@code RequestProperties} to be used by the
|
||||
* {@link HttpDataSource} instance.
|
||||
* @return A {@link HttpDataSource} instance.
|
||||
*/
|
||||
protected abstract HttpDataSource createDataSourceInternal();
|
||||
protected abstract HttpDataSource createDataSourceInternal(RequestProperties
|
||||
defaultRequestProperties);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user