1
0
mirror of https://github.com/square/okhttp.git synced 2025-08-08 23:42:08 +03:00

Import jsr305 and use it to mark @Nullable stuff.

This library is a provided dependency and is not necessary to be included
by OkHttp users.

This currently covers the okhttp and okhttp-logging-interceptor modules
only. It does not cover the 'internal' package in OkHttp, or its test cases.
We can add those as needed.
This commit is contained in:
jwilson
2017-05-06 12:13:09 -04:00
parent 254b0752e5
commit 011b2ee76d
33 changed files with 220 additions and 164 deletions

View File

@@ -18,6 +18,11 @@
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>

View File

@@ -0,0 +1,3 @@
/** An OkHttp interceptor which logs HTTP request and response data. */
@javax.annotation.ParametersAreNonnullByDefault
package okhttp3.logging;

View File

@@ -22,6 +22,11 @@
<artifactId>android</artifactId> <artifactId>android</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -18,6 +18,7 @@ package okhttp3;
import java.net.Proxy; import java.net.Proxy;
import java.net.ProxySelector; import java.net.ProxySelector;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
@@ -42,15 +43,16 @@ public final class Address {
final List<Protocol> protocols; final List<Protocol> protocols;
final List<ConnectionSpec> connectionSpecs; final List<ConnectionSpec> connectionSpecs;
final ProxySelector proxySelector; final ProxySelector proxySelector;
final Proxy proxy; final @Nullable Proxy proxy;
final SSLSocketFactory sslSocketFactory; final @Nullable SSLSocketFactory sslSocketFactory;
final HostnameVerifier hostnameVerifier; final @Nullable HostnameVerifier hostnameVerifier;
final CertificatePinner certificatePinner; final @Nullable CertificatePinner certificatePinner;
public Address(String uriHost, int uriPort, Dns dns, SocketFactory socketFactory, public Address(String uriHost, int uriPort, Dns dns, SocketFactory socketFactory,
SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier, @Nullable SSLSocketFactory sslSocketFactory, @Nullable HostnameVerifier hostnameVerifier,
CertificatePinner certificatePinner, Authenticator proxyAuthenticator, Proxy proxy, @Nullable CertificatePinner certificatePinner, Authenticator proxyAuthenticator,
List<Protocol> protocols, List<ConnectionSpec> connectionSpecs, ProxySelector proxySelector) { @Nullable Proxy proxy, List<Protocol> protocols, List<ConnectionSpec> connectionSpecs,
ProxySelector proxySelector) {
this.url = new HttpUrl.Builder() this.url = new HttpUrl.Builder()
.scheme(sslSocketFactory != null ? "https" : "http") .scheme(sslSocketFactory != null ? "https" : "http")
.host(uriHost) .host(uriHost)
@@ -130,26 +132,26 @@ public final class Address {
* Returns this address's explicitly-specified HTTP proxy, or null to delegate to the {@linkplain * Returns this address's explicitly-specified HTTP proxy, or null to delegate to the {@linkplain
* #proxySelector proxy selector}. * #proxySelector proxy selector}.
*/ */
public Proxy proxy() { public @Nullable Proxy proxy() {
return proxy; return proxy;
} }
/** Returns the SSL socket factory, or null if this is not an HTTPS address. */ /** Returns the SSL socket factory, or null if this is not an HTTPS address. */
public SSLSocketFactory sslSocketFactory() { public @Nullable SSLSocketFactory sslSocketFactory() {
return sslSocketFactory; return sslSocketFactory;
} }
/** Returns the hostname verifier, or null if this is not an HTTPS address. */ /** Returns the hostname verifier, or null if this is not an HTTPS address. */
public HostnameVerifier hostnameVerifier() { public @Nullable HostnameVerifier hostnameVerifier() {
return hostnameVerifier; return hostnameVerifier;
} }
/** Returns this address's certificate pinner, or null if this is not an HTTPS address. */ /** Returns this address's certificate pinner, or null if this is not an HTTPS address. */
public CertificatePinner certificatePinner() { public @Nullable CertificatePinner certificatePinner() {
return certificatePinner; return certificatePinner;
} }
@Override public boolean equals(Object other) { @Override public boolean equals(@Nullable Object other) {
return other instanceof Address return other instanceof Address
&& url.equals(((Address) other).url) && url.equals(((Address) other).url)
&& equalsNonHost((Address) other); && equalsNonHost((Address) other);

View File

@@ -16,6 +16,7 @@
package okhttp3; package okhttp3;
import java.io.IOException; import java.io.IOException;
import javax.annotation.Nullable;
/** /**
* Responds to an authentication challenge from either a remote web server or a proxy server. * Responds to an authentication challenge from either a remote web server or a proxy server.
@@ -70,5 +71,5 @@ public interface Authenticator {
* Returns a request that includes a credential to satisfy an authentication challenge in {@code * Returns a request that includes a credential to satisfy an authentication challenge in {@code
* response}. Returns null if the challenge cannot be satisfied. * response}. Returns null if the challenge cannot be satisfied.
*/ */
Request authenticate(Route route, Response response) throws IOException; @Nullable Request authenticate(Route route, Response response) throws IOException;
} }

View File

@@ -28,6 +28,7 @@ import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.cache.CacheRequest; import okhttp3.internal.cache.CacheRequest;
import okhttp3.internal.cache.CacheStrategy; import okhttp3.internal.cache.CacheStrategy;
@@ -186,7 +187,7 @@ public final class Cache implements Closeable, Flushable {
return ByteString.encodeUtf8(url.toString()).md5().hex(); return ByteString.encodeUtf8(url.toString()).md5().hex();
} }
Response get(Request request) { @Nullable Response get(Request request) {
String key = key(request.url()); String key = key(request.url());
DiskLruCache.Snapshot snapshot; DiskLruCache.Snapshot snapshot;
Entry entry; Entry entry;
@@ -217,7 +218,7 @@ public final class Cache implements Closeable, Flushable {
return response; return response;
} }
CacheRequest put(Response response) { @Nullable CacheRequest put(Response response) {
String requestMethod = response.request().method(); String requestMethod = response.request().method();
if (HttpMethod.invalidatesCache(response.request().method())) { if (HttpMethod.invalidatesCache(response.request().method())) {
@@ -273,7 +274,7 @@ public final class Cache implements Closeable, Flushable {
} }
} }
private void abortQuietly(DiskLruCache.Editor editor) { private void abortQuietly(@Nullable DiskLruCache.Editor editor) {
// Give up because the cache cannot be written. // Give up because the cache cannot be written.
try { try {
if (editor != null) { if (editor != null) {
@@ -327,7 +328,7 @@ public final class Cache implements Closeable, Flushable {
return new Iterator<String>() { return new Iterator<String>() {
final Iterator<DiskLruCache.Snapshot> delegate = cache.snapshots(); final Iterator<DiskLruCache.Snapshot> delegate = cache.snapshots();
String nextUrl; @Nullable String nextUrl;
boolean canRemove; boolean canRemove;
@Override public boolean hasNext() { @Override public boolean hasNext() {
@@ -484,7 +485,7 @@ public final class Cache implements Closeable, Flushable {
private final int code; private final int code;
private final String message; private final String message;
private final Headers responseHeaders; private final Headers responseHeaders;
private final Handshake handshake; private final @Nullable Handshake handshake;
private final long sentRequestMillis; private final long sentRequestMillis;
private final long receivedResponseMillis; private final long receivedResponseMillis;
@@ -732,8 +733,8 @@ public final class Cache implements Closeable, Flushable {
private static class CacheResponseBody extends ResponseBody { private static class CacheResponseBody extends ResponseBody {
final DiskLruCache.Snapshot snapshot; final DiskLruCache.Snapshot snapshot;
private final BufferedSource bodySource; private final BufferedSource bodySource;
private final String contentType; private final @Nullable String contentType;
private final String contentLength; private final @Nullable String contentLength;
CacheResponseBody(final DiskLruCache.Snapshot snapshot, CacheResponseBody(final DiskLruCache.Snapshot snapshot,
String contentType, String contentLength) { String contentType, String contentLength) {

View File

@@ -1,6 +1,7 @@
package okhttp3; package okhttp3;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import okhttp3.internal.http.HttpHeaders; import okhttp3.internal.http.HttpHeaders;
/** /**
@@ -39,11 +40,12 @@ public final class CacheControl {
private final boolean onlyIfCached; private final boolean onlyIfCached;
private final boolean noTransform; private final boolean noTransform;
String headerValue; // Lazily computed, null if absent. @Nullable String headerValue; // Lazily computed, null if absent.
private CacheControl(boolean noCache, boolean noStore, int maxAgeSeconds, int sMaxAgeSeconds, private CacheControl(boolean noCache, boolean noStore, int maxAgeSeconds, int sMaxAgeSeconds,
boolean isPrivate, boolean isPublic, boolean mustRevalidate, int maxStaleSeconds, boolean isPrivate, boolean isPublic, boolean mustRevalidate, int maxStaleSeconds,
int minFreshSeconds, boolean onlyIfCached, boolean noTransform, String headerValue) { int minFreshSeconds, boolean onlyIfCached, boolean noTransform,
@Nullable String headerValue) {
this.noCache = noCache; this.noCache = noCache;
this.noStore = noStore; this.noStore = noStore;
this.maxAgeSeconds = maxAgeSeconds; this.maxAgeSeconds = maxAgeSeconds;

View File

@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable;
import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLPeerUnverifiedException;
import okhttp3.internal.tls.CertificateChainCleaner; import okhttp3.internal.tls.CertificateChainCleaner;
import okio.ByteString; import okio.ByteString;
@@ -128,14 +129,14 @@ public final class CertificatePinner {
public static final CertificatePinner DEFAULT = new Builder().build(); public static final CertificatePinner DEFAULT = new Builder().build();
private final Set<Pin> pins; private final Set<Pin> pins;
private final CertificateChainCleaner certificateChainCleaner; private final @Nullable CertificateChainCleaner certificateChainCleaner;
CertificatePinner(Set<Pin> pins, CertificateChainCleaner certificateChainCleaner) { CertificatePinner(Set<Pin> pins, @Nullable CertificateChainCleaner certificateChainCleaner) {
this.pins = pins; this.pins = pins;
this.certificateChainCleaner = certificateChainCleaner; this.certificateChainCleaner = certificateChainCleaner;
} }
@Override public boolean equals(Object other) { @Override public boolean equals(@Nullable Object other) {
if (other == this) return true; if (other == this) return true;
return other instanceof CertificatePinner return other instanceof CertificatePinner
&& (equal(certificateChainCleaner, ((CertificatePinner) other).certificateChainCleaner) && (equal(certificateChainCleaner, ((CertificatePinner) other).certificateChainCleaner)

View File

@@ -15,6 +15,8 @@
*/ */
package okhttp3; package okhttp3;
import javax.annotation.Nullable;
/** An RFC 2617 challenge. */ /** An RFC 2617 challenge. */
public final class Challenge { public final class Challenge {
private final String scheme; private final String scheme;
@@ -37,10 +39,10 @@ public final class Challenge {
return realm; return realm;
} }
@Override public boolean equals(Object o) { @Override public boolean equals(@Nullable Object other) {
return o instanceof Challenge return other instanceof Challenge
&& ((Challenge) o).scheme.equals(scheme) && ((Challenge) other).scheme.equals(scheme)
&& ((Challenge) o).realm.equals(realm); && ((Challenge) other).realm.equals(realm);
} }
@Override public int hashCode() { @Override public int hashCode() {

View File

@@ -17,6 +17,7 @@
package okhttp3; package okhttp3;
import java.net.Socket; import java.net.Socket;
import javax.annotation.Nullable;
/** /**
* The sockets and streams of an HTTP, HTTPS, or HTTPS+HTTP/2 connection. May be used for multiple * The sockets and streams of an HTTP, HTTPS, or HTTPS+HTTP/2 connection. May be used for multiple
@@ -82,7 +83,7 @@ public interface Connection {
* Returns the TLS handshake used to establish this connection, or null if the connection is not * Returns the TLS handshake used to establish this connection, or null if the connection is not
* HTTPS. * HTTPS.
*/ */
Handshake handshake(); @Nullable Handshake handshake();
/** /**
* Returns the protocol negotiated by this connection, or {@link Protocol#HTTP_1_1} if no protocol * Returns the protocol negotiated by this connection, or {@link Protocol#HTTP_1_1} if no protocol

View File

@@ -27,6 +27,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.connection.RealConnection; import okhttp3.internal.connection.RealConnection;
import okhttp3.internal.connection.RouteDatabase; import okhttp3.internal.connection.RouteDatabase;
@@ -118,7 +119,7 @@ public final class ConnectionPool {
* Returns a recycled connection to {@code address}, or null if no such connection exists. The * Returns a recycled connection to {@code address}, or null if no such connection exists. The
* route is null if the address has not yet been routed. * route is null if the address has not yet been routed.
*/ */
RealConnection get(Address address, StreamAllocation streamAllocation, Route route) { @Nullable RealConnection get(Address address, StreamAllocation streamAllocation, Route route) {
assert (Thread.holdsLock(this)); assert (Thread.holdsLock(this));
for (RealConnection connection : connections) { for (RealConnection connection : connections) {
if (connection.isEligible(address, route)) { if (connection.isEligible(address, route)) {
@@ -133,7 +134,7 @@ public final class ConnectionPool {
* Replaces the connection held by {@code streamAllocation} with a shared connection if possible. * Replaces the connection held by {@code streamAllocation} with a shared connection if possible.
* This recovers when multiple multiplexed connections are created concurrently. * This recovers when multiple multiplexed connections are created concurrently.
*/ */
Socket deduplicate(Address address, StreamAllocation streamAllocation) { @Nullable Socket deduplicate(Address address, StreamAllocation streamAllocation) {
assert (Thread.holdsLock(this)); assert (Thread.holdsLock(this));
for (RealConnection connection : connections) { for (RealConnection connection : connections) {
if (connection.isEligible(address, null) if (connection.isEligible(address, null)

View File

@@ -17,6 +17,7 @@ package okhttp3;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import okhttp3.internal.Util; import okhttp3.internal.Util;
@@ -82,8 +83,8 @@ public final class ConnectionSpec {
final boolean tls; final boolean tls;
final boolean supportsTlsExtensions; final boolean supportsTlsExtensions;
final String[] cipherSuites; final @Nullable String[] cipherSuites;
final String[] tlsVersions; final @Nullable String[] tlsVersions;
ConnectionSpec(Builder builder) { ConnectionSpec(Builder builder) {
this.tls = builder.tls; this.tls = builder.tls;
@@ -97,18 +98,18 @@ public final class ConnectionSpec {
} }
/** /**
* Returns the cipher suites to use for a connection. Returns {@code null} if all of the SSL * Returns the cipher suites to use for a connection. Returns null if all of the SSL socket's
* socket's enabled cipher suites should be used. * enabled cipher suites should be used.
*/ */
public List<CipherSuite> cipherSuites() { public @Nullable List<CipherSuite> cipherSuites() {
return cipherSuites != null ? CipherSuite.forJavaNames(cipherSuites) : null; return cipherSuites != null ? CipherSuite.forJavaNames(cipherSuites) : null;
} }
/** /**
* Returns the TLS versions to use when negotiating a connection. Returns {@code null} if all of * Returns the TLS versions to use when negotiating a connection. Returns null if all of the SSL
* the SSL socket's enabled TLS versions should be used. * socket's enabled TLS versions should be used.
*/ */
public List<TlsVersion> tlsVersions() { public @Nullable List<TlsVersion> tlsVersions() {
return tlsVersions != null ? TlsVersion.forJavaNames(tlsVersions) : null; return tlsVersions != null ? TlsVersion.forJavaNames(tlsVersions) : null;
} }
@@ -185,7 +186,7 @@ public final class ConnectionSpec {
return true; return true;
} }
@Override public boolean equals(Object other) { @Override public boolean equals(@Nullable Object other) {
if (!(other instanceof ConnectionSpec)) return false; if (!(other instanceof ConnectionSpec)) return false;
if (other == this) return true; if (other == this) return true;
@@ -227,8 +228,8 @@ public final class ConnectionSpec {
public static final class Builder { public static final class Builder {
boolean tls; boolean tls;
String[] cipherSuites; @Nullable String[] cipherSuites;
String[] tlsVersions; @Nullable String[] tlsVersions;
boolean supportsTlsExtensions; boolean supportsTlsExtensions;
Builder(boolean tls) { Builder(boolean tls) {

View File

@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.http.HttpDate; import okhttp3.internal.http.HttpDate;
import okhttp3.internal.publicsuffix.PublicSuffixDatabase; import okhttp3.internal.publicsuffix.PublicSuffixDatabase;
@@ -214,11 +215,11 @@ public final class Cookie {
* Attempt to parse a {@code Set-Cookie} HTTP header value {@code setCookie} as a cookie. Returns * Attempt to parse a {@code Set-Cookie} HTTP header value {@code setCookie} as a cookie. Returns
* null if {@code setCookie} is not a well-formed cookie. * null if {@code setCookie} is not a well-formed cookie.
*/ */
public static Cookie parse(HttpUrl url, String setCookie) { public static @Nullable Cookie parse(HttpUrl url, String setCookie) {
return parse(System.currentTimeMillis(), url, setCookie); return parse(System.currentTimeMillis(), url, setCookie);
} }
static Cookie parse(long currentTimeMillis, HttpUrl url, String setCookie) { static @Nullable Cookie parse(long currentTimeMillis, HttpUrl url, String setCookie) {
int pos = 0; int pos = 0;
int limit = setCookie.length(); int limit = setCookie.length();
int cookiePairEnd = delimiterOffset(setCookie, pos, limit, ';'); int cookiePairEnd = delimiterOffset(setCookie, pos, limit, ';');
@@ -581,7 +582,7 @@ public final class Cookie {
return result.toString(); return result.toString();
} }
@Override public boolean equals(Object other) { @Override public boolean equals(@Nullable Object other) {
if (!(other instanceof Cookie)) return false; if (!(other instanceof Cookie)) return false;
Cookie that = (Cookie) other; Cookie that = (Cookie) other;
return that.name.equals(name) return that.name.equals(name)

View File

@@ -25,6 +25,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import okhttp3.RealCall.AsyncCall; import okhttp3.RealCall.AsyncCall;
import okhttp3.internal.Util; import okhttp3.internal.Util;
@@ -38,10 +39,10 @@ import okhttp3.internal.Util;
public final class Dispatcher { public final class Dispatcher {
private int maxRequests = 64; private int maxRequests = 64;
private int maxRequestsPerHost = 5; private int maxRequestsPerHost = 5;
private Runnable idleCallback; private @Nullable Runnable idleCallback;
/** Executes calls. Created lazily. */ /** Executes calls. Created lazily. */
private ExecutorService executorService; private @Nullable ExecutorService executorService;
/** Ready async calls in the order they'll be run. */ /** Ready async calls in the order they'll be run. */
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
@@ -119,7 +120,7 @@ public final class Dispatcher {
* means that if you are doing synchronous calls the network layer will not truly be idle until * means that if you are doing synchronous calls the network layer will not truly be idle until
* every returned {@link Response} has been closed. * every returned {@link Response} has been closed.
*/ */
public synchronized void setIdleCallback(Runnable idleCallback) { public synchronized void setIdleCallback(@Nullable Runnable idleCallback) {
this.idleCallback = idleCallback; this.idleCallback = idleCallback;
} }

View File

@@ -18,6 +18,7 @@ package okhttp3;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okio.Buffer; import okio.Buffer;
import okio.BufferedSink; import okio.BufferedSink;
@@ -76,7 +77,7 @@ public final class FormBody extends RequestBody {
* to awkward operations like measuring the encoded length of header strings, or the * to awkward operations like measuring the encoded length of header strings, or the
* length-in-digits of an encoded integer. * length-in-digits of an encoded integer.
*/ */
private long writeOrCountBytes(BufferedSink sink, boolean countBytes) { private long writeOrCountBytes(@Nullable BufferedSink sink, boolean countBytes) {
long byteCount = 0L; long byteCount = 0L;
Buffer buffer; Buffer buffer;

View File

@@ -20,6 +20,7 @@ import java.security.cert.Certificate;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import okhttp3.internal.Util; import okhttp3.internal.Util;
@@ -99,7 +100,7 @@ public final class Handshake {
} }
/** Returns the remote peer's principle, or null if that peer is anonymous. */ /** Returns the remote peer's principle, or null if that peer is anonymous. */
public Principal peerPrincipal() { public @Nullable Principal peerPrincipal() {
return !peerCertificates.isEmpty() return !peerCertificates.isEmpty()
? ((X509Certificate) peerCertificates.get(0)).getSubjectX500Principal() ? ((X509Certificate) peerCertificates.get(0)).getSubjectX500Principal()
: null; : null;
@@ -111,13 +112,13 @@ public final class Handshake {
} }
/** Returns the local principle, or null if this peer is anonymous. */ /** Returns the local principle, or null if this peer is anonymous. */
public Principal localPrincipal() { public @Nullable Principal localPrincipal() {
return !localCertificates.isEmpty() return !localCertificates.isEmpty()
? ((X509Certificate) localCertificates.get(0)).getSubjectX500Principal() ? ((X509Certificate) localCertificates.get(0)).getSubjectX500Principal()
: null; : null;
} }
@Override public boolean equals(Object other) { @Override public boolean equals(@Nullable Object other) {
if (!(other instanceof Handshake)) return false; if (!(other instanceof Handshake)) return false;
Handshake that = (Handshake) other; Handshake that = (Handshake) other;
return tlsVersion.equals(that.tlsVersion) return tlsVersion.equals(that.tlsVersion)

View File

@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.http.HttpDate; import okhttp3.internal.http.HttpDate;
@@ -58,7 +59,7 @@ public final class Headers {
} }
/** Returns the last value corresponding to the specified field, or null. */ /** Returns the last value corresponding to the specified field, or null. */
public String get(String name) { public @Nullable String get(String name) {
return get(namesAndValues, name); return get(namesAndValues, name);
} }
@@ -66,7 +67,7 @@ public final class Headers {
* Returns the last value corresponding to the specified field parsed as an HTTP date, or null if * Returns the last value corresponding to the specified field parsed as an HTTP date, or null if
* either the field is absent or cannot be parsed as a date. * either the field is absent or cannot be parsed as a date.
*/ */
public Date getDate(String name) { public @Nullable Date getDate(String name) {
String value = get(name); String value = get(name);
return value != null ? HttpDate.parse(value) : null; return value != null ? HttpDate.parse(value) : null;
} }
@@ -141,7 +142,7 @@ public final class Headers {
* Applications that require semantically equal headers should convert them into a canonical form * Applications that require semantically equal headers should convert them into a canonical form
* before comparing them for equality. * before comparing them for equality.
*/ */
@Override public boolean equals(Object other) { @Override public boolean equals(@Nullable Object other) {
return other instanceof Headers return other instanceof Headers
&& Arrays.equals(((Headers) other).namesAndValues, namesAndValues); && Arrays.equals(((Headers) other).namesAndValues, namesAndValues);
} }

View File

@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable;
import okhttp3.internal.publicsuffix.PublicSuffixDatabase; import okhttp3.internal.publicsuffix.PublicSuffixDatabase;
import okio.Buffer; import okio.Buffer;
@@ -324,10 +325,10 @@ public final class HttpUrl {
* non-empty, but never null. Values are null if the name has no corresponding '=' separator, or * non-empty, but never null. Values are null if the name has no corresponding '=' separator, or
* empty, or non-empty. * empty, or non-empty.
*/ */
private final List<String> queryNamesAndValues; private final @Nullable List<String> queryNamesAndValues;
/** Decoded fragment. */ /** Decoded fragment. */
private final String fragment; private final @Nullable String fragment;
/** Canonical URL. */ /** Canonical URL. */
private final String url; private final String url;
@@ -606,7 +607,7 @@ public final class HttpUrl {
* <tr><td>{@code http://host/?a=apple&b}</td><td>{@code "a=apple&b"}</td></tr> * <tr><td>{@code http://host/?a=apple&b}</td><td>{@code "a=apple&b"}</td></tr>
* </table> * </table>
*/ */
public String encodedQuery() { public @Nullable String encodedQuery() {
if (queryNamesAndValues == null) return null; // No query. if (queryNamesAndValues == null) return null; // No query.
int queryStart = url.indexOf('?') + 1; int queryStart = url.indexOf('?') + 1;
int queryEnd = delimiterOffset(url, queryStart + 1, url.length(), '#'); int queryEnd = delimiterOffset(url, queryStart + 1, url.length(), '#');
@@ -666,7 +667,7 @@ public final class HttpUrl {
* <tr><td>{@code http://host/?a=apple&b}</td><td>{@code "a=apple&b"}</td></tr> * <tr><td>{@code http://host/?a=apple&b}</td><td>{@code "a=apple&b"}</td></tr>
* </table> * </table>
*/ */
public String query() { public @Nullable String query() {
if (queryNamesAndValues == null) return null; // No query. if (queryNamesAndValues == null) return null; // No query.
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
namesAndValuesToQueryString(result, queryNamesAndValues); namesAndValuesToQueryString(result, queryNamesAndValues);
@@ -704,7 +705,7 @@ public final class HttpUrl {
* <tr><td>{@code http://host/?a=apple&b}</td><td>{@code "apple"}</td></tr> * <tr><td>{@code http://host/?a=apple&b}</td><td>{@code "apple"}</td></tr>
* </table> * </table>
*/ */
public String queryParameter(String name) { public @Nullable String queryParameter(String name) {
if (queryNamesAndValues == null) return null; if (queryNamesAndValues == null) return null;
for (int i = 0, size = queryNamesAndValues.size(); i < size; i += 2) { for (int i = 0, size = queryNamesAndValues.size(); i < size; i += 2) {
if (name.equals(queryNamesAndValues.get(i))) { if (name.equals(queryNamesAndValues.get(i))) {
@@ -821,7 +822,7 @@ public final class HttpUrl {
* <tr><td>{@code http://host/#abc|def}</td><td>{@code "abc|def"}</td></tr> * <tr><td>{@code http://host/#abc|def}</td><td>{@code "abc|def"}</td></tr>
* </table> * </table>
*/ */
public String encodedFragment() { public @Nullable String encodedFragment() {
if (fragment == null) return null; if (fragment == null) return null;
int fragmentStart = url.indexOf('#') + 1; int fragmentStart = url.indexOf('#') + 1;
return url.substring(fragmentStart); return url.substring(fragmentStart);
@@ -839,7 +840,7 @@ public final class HttpUrl {
* <tr><td>{@code http://host/#abc|def}</td><td>{@code "abc|def"}</td></tr> * <tr><td>{@code http://host/#abc|def}</td><td>{@code "abc|def"}</td></tr>
* </table> * </table>
*/ */
public String fragment() { public @Nullable String fragment() {
return fragment; return fragment;
} }
@@ -860,7 +861,7 @@ public final class HttpUrl {
* Returns the URL that would be retrieved by following {@code link} from this URL, or null if * Returns the URL that would be retrieved by following {@code link} from this URL, or null if
* the resulting URL is not well-formed. * the resulting URL is not well-formed.
*/ */
public HttpUrl resolve(String link) { public @Nullable HttpUrl resolve(String link) {
Builder builder = newBuilder(link); Builder builder = newBuilder(link);
return builder != null ? builder.build() : null; return builder != null ? builder.build() : null;
} }
@@ -884,7 +885,7 @@ public final class HttpUrl {
* Returns a builder for the URL that would be retrieved by following {@code link} from this URL, * Returns a builder for the URL that would be retrieved by following {@code link} from this URL,
* or null if the resulting URL is not well-formed. * or null if the resulting URL is not well-formed.
*/ */
public Builder newBuilder(String link) { public @Nullable Builder newBuilder(String link) {
Builder builder = new Builder(); Builder builder = new Builder();
Builder.ParseResult result = builder.parse(this, link); Builder.ParseResult result = builder.parse(this, link);
return result == Builder.ParseResult.SUCCESS ? builder : null; return result == Builder.ParseResult.SUCCESS ? builder : null;
@@ -894,7 +895,7 @@ public final class HttpUrl {
* Returns a new {@code HttpUrl} representing {@code url} if it is a well-formed HTTP or HTTPS * Returns a new {@code HttpUrl} representing {@code url} if it is a well-formed HTTP or HTTPS
* URL, or null if it isn't. * URL, or null if it isn't.
*/ */
public static HttpUrl parse(String url) { public static @Nullable HttpUrl parse(String url) {
Builder builder = new Builder(); Builder builder = new Builder();
Builder.ParseResult result = builder.parse(null, url); Builder.ParseResult result = builder.parse(null, url);
return result == Builder.ParseResult.SUCCESS ? builder.build() : null; return result == Builder.ParseResult.SUCCESS ? builder.build() : null;
@@ -904,7 +905,7 @@ public final class HttpUrl {
* Returns an {@link HttpUrl} for {@code url} if its protocol is {@code http} or {@code https}, or * Returns an {@link HttpUrl} for {@code url} if its protocol is {@code http} or {@code https}, or
* null if it has any other protocol. * null if it has any other protocol.
*/ */
public static HttpUrl get(URL url) { public static @Nullable HttpUrl get(URL url) {
return parse(url.toString()); return parse(url.toString());
} }
@@ -931,12 +932,12 @@ public final class HttpUrl {
} }
} }
public static HttpUrl get(URI uri) { public static @Nullable HttpUrl get(URI uri) {
return parse(uri.toString()); return parse(uri.toString());
} }
@Override public boolean equals(Object o) { @Override public boolean equals(@Nullable Object other) {
return o instanceof HttpUrl && ((HttpUrl) o).url.equals(url); return other instanceof HttpUrl && ((HttpUrl) other).url.equals(url);
} }
@Override public int hashCode() { @Override public int hashCode() {
@@ -966,20 +967,20 @@ public final class HttpUrl {
* <tr><td>{@code http://127.0.0.1}</td><td>null</td></tr> * <tr><td>{@code http://127.0.0.1}</td><td>null</td></tr>
* </table> * </table>
*/ */
public String topPrivateDomain() { public @Nullable String topPrivateDomain() {
if (verifyAsIpAddress(host)) return null; if (verifyAsIpAddress(host)) return null;
return PublicSuffixDatabase.get().getEffectiveTldPlusOne(host); return PublicSuffixDatabase.get().getEffectiveTldPlusOne(host);
} }
public static final class Builder { public static final class Builder {
String scheme; @Nullable String scheme;
String encodedUsername = ""; String encodedUsername = "";
String encodedPassword = ""; String encodedPassword = "";
String host; @Nullable String host;
int port = -1; int port = -1;
final List<String> encodedPathSegments = new ArrayList<>(); final List<String> encodedPathSegments = new ArrayList<>();
List<String> encodedQueryNamesAndValues; @Nullable List<String> encodedQueryNamesAndValues;
String encodedFragment; @Nullable String encodedFragment;
public Builder() { public Builder() {
encodedPathSegments.add(""); // The default path is '/' which needs a trailing space. encodedPathSegments.add(""); // The default path is '/' which needs a trailing space.
@@ -1133,7 +1134,7 @@ public final class HttpUrl {
return this; return this;
} }
public Builder query(String query) { public Builder query(@Nullable String query) {
this.encodedQueryNamesAndValues = query != null this.encodedQueryNamesAndValues = query != null
? queryStringToNamesAndValues(canonicalize( ? queryStringToNamesAndValues(canonicalize(
query, QUERY_ENCODE_SET, false, false, true, true)) query, QUERY_ENCODE_SET, false, false, true, true))
@@ -1141,7 +1142,7 @@ public final class HttpUrl {
return this; return this;
} }
public Builder encodedQuery(String encodedQuery) { public Builder encodedQuery(@Nullable String encodedQuery) {
this.encodedQueryNamesAndValues = encodedQuery != null this.encodedQueryNamesAndValues = encodedQuery != null
? queryStringToNamesAndValues( ? queryStringToNamesAndValues(
canonicalize(encodedQuery, QUERY_ENCODE_SET, true, false, true, true)) canonicalize(encodedQuery, QUERY_ENCODE_SET, true, false, true, true))
@@ -1150,7 +1151,7 @@ public final class HttpUrl {
} }
/** Encodes the query parameter using UTF-8 and adds it to this URL's query string. */ /** Encodes the query parameter using UTF-8 and adds it to this URL's query string. */
public Builder addQueryParameter(String name, String value) { public Builder addQueryParameter(String name, @Nullable String value) {
if (name == null) throw new NullPointerException("name == null"); if (name == null) throw new NullPointerException("name == null");
if (encodedQueryNamesAndValues == null) encodedQueryNamesAndValues = new ArrayList<>(); if (encodedQueryNamesAndValues == null) encodedQueryNamesAndValues = new ArrayList<>();
encodedQueryNamesAndValues.add( encodedQueryNamesAndValues.add(
@@ -1162,7 +1163,7 @@ public final class HttpUrl {
} }
/** Adds the pre-encoded query parameter to this URL's query string. */ /** Adds the pre-encoded query parameter to this URL's query string. */
public Builder addEncodedQueryParameter(String encodedName, String encodedValue) { public Builder addEncodedQueryParameter(String encodedName, @Nullable String encodedValue) {
if (encodedName == null) throw new NullPointerException("encodedName == null"); if (encodedName == null) throw new NullPointerException("encodedName == null");
if (encodedQueryNamesAndValues == null) encodedQueryNamesAndValues = new ArrayList<>(); if (encodedQueryNamesAndValues == null) encodedQueryNamesAndValues = new ArrayList<>();
encodedQueryNamesAndValues.add( encodedQueryNamesAndValues.add(
@@ -1173,13 +1174,13 @@ public final class HttpUrl {
return this; return this;
} }
public Builder setQueryParameter(String name, String value) { public Builder setQueryParameter(String name, @Nullable String value) {
removeAllQueryParameters(name); removeAllQueryParameters(name);
addQueryParameter(name, value); addQueryParameter(name, value);
return this; return this;
} }
public Builder setEncodedQueryParameter(String encodedName, String encodedValue) { public Builder setEncodedQueryParameter(String encodedName, @Nullable String encodedValue) {
removeAllEncodedQueryParameters(encodedName); removeAllEncodedQueryParameters(encodedName);
addEncodedQueryParameter(encodedName, encodedValue); addEncodedQueryParameter(encodedName, encodedValue);
return this; return this;
@@ -1215,14 +1216,14 @@ public final class HttpUrl {
} }
} }
public Builder fragment(String fragment) { public Builder fragment(@Nullable String fragment) {
this.encodedFragment = fragment != null this.encodedFragment = fragment != null
? canonicalize(fragment, FRAGMENT_ENCODE_SET, false, false, false, false) ? canonicalize(fragment, FRAGMENT_ENCODE_SET, false, false, false, false)
: null; : null;
return this; return this;
} }
public Builder encodedFragment(String encodedFragment) { public Builder encodedFragment(@Nullable String encodedFragment) {
this.encodedFragment = encodedFragment != null this.encodedFragment = encodedFragment != null
? canonicalize(encodedFragment, FRAGMENT_ENCODE_SET, true, false, false, false) ? canonicalize(encodedFragment, FRAGMENT_ENCODE_SET, true, false, false, false)
: null; : null;
@@ -1313,7 +1314,7 @@ public final class HttpUrl {
INVALID_HOST, INVALID_HOST,
} }
ParseResult parse(HttpUrl base, String input) { ParseResult parse(@Nullable HttpUrl base, String input) {
int pos = skipLeadingAsciiWhitespace(input, 0, input.length()); int pos = skipLeadingAsciiWhitespace(input, 0, input.length());
int limit = skipTrailingAsciiWhitespace(input, pos, input.length()); int limit = skipTrailingAsciiWhitespace(input, pos, input.length());
@@ -1598,7 +1599,7 @@ public final class HttpUrl {
} }
/** Decodes an IPv6 address like 1111:2222:3333:4444:5555:6666:7777:8888 or ::1. */ /** Decodes an IPv6 address like 1111:2222:3333:4444:5555:6666:7777:8888 or ::1. */
private static InetAddress decodeIpv6(String input, int pos, int limit) { private static @Nullable InetAddress decodeIpv6(String input, int pos, int limit) {
byte[] address = new byte[16]; byte[] address = new byte[16];
int b = 0; int b = 0;
int compress = -1; int compress = -1;

View File

@@ -16,6 +16,7 @@
package okhttp3; package okhttp3;
import java.io.IOException; import java.io.IOException;
import javax.annotation.Nullable;
/** /**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding * Observes, modifies, and potentially short-circuits requests going out and the corresponding
@@ -30,6 +31,10 @@ public interface Interceptor {
Response proceed(Request request) throws IOException; Response proceed(Request request) throws IOException;
Connection connection(); /**
* Returns the connection the request will be executed on. This is only available in the chains
* of network interceptors; for application interceptors this is always null.
*/
@Nullable Connection connection();
} }
} }

View File

@@ -19,6 +19,7 @@ import java.nio.charset.Charset;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Nullable;
/** /**
* An <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a> Media Type, appropriate to describe * An <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a> Media Type, appropriate to describe
@@ -34,9 +35,9 @@ public final class MediaType {
private final String mediaType; private final String mediaType;
private final String type; private final String type;
private final String subtype; private final String subtype;
private final String charset; private final @Nullable String charset;
private MediaType(String mediaType, String type, String subtype, String charset) { private MediaType(String mediaType, String type, String subtype, @Nullable String charset) {
this.mediaType = mediaType; this.mediaType = mediaType;
this.type = type; this.type = type;
this.subtype = subtype; this.subtype = subtype;
@@ -47,7 +48,7 @@ public final class MediaType {
* Returns a media type for {@code string}, or null if {@code string} is not a well-formed media * Returns a media type for {@code string}, or null if {@code string} is not a well-formed media
* type. * type.
*/ */
public static MediaType parse(String string) { public static @Nullable MediaType parse(String string) {
Matcher typeSubtype = TYPE_SUBTYPE.matcher(string); Matcher typeSubtype = TYPE_SUBTYPE.matcher(string);
if (!typeSubtype.lookingAt()) return null; if (!typeSubtype.lookingAt()) return null;
String type = typeSubtype.group(1).toLowerCase(Locale.US); String type = typeSubtype.group(1).toLowerCase(Locale.US);
@@ -99,7 +100,7 @@ public final class MediaType {
/** /**
* Returns the charset of this media type, or null if this media type doesn't specify a charset. * Returns the charset of this media type, or null if this media type doesn't specify a charset.
*/ */
public Charset charset() { public @Nullable Charset charset() {
return charset(null); return charset(null);
} }
@@ -107,7 +108,7 @@ public final class MediaType {
* Returns the charset of this media type, or {@code defaultValue} if either this media type * Returns the charset of this media type, or {@code defaultValue} if either this media type
* doesn't specify a charset, of it its charset is unsupported by the current runtime. * doesn't specify a charset, of it its charset is unsupported by the current runtime.
*/ */
public Charset charset(Charset defaultValue) { public @Nullable Charset charset(@Nullable Charset defaultValue) {
try { try {
return charset != null ? Charset.forName(charset) : defaultValue; return charset != null ? Charset.forName(charset) : defaultValue;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@@ -123,8 +124,8 @@ public final class MediaType {
return mediaType; return mediaType;
} }
@Override public boolean equals(Object o) { @Override public boolean equals(@Nullable Object other) {
return o instanceof MediaType && ((MediaType) o).mediaType.equals(mediaType); return other instanceof MediaType && ((MediaType) other).mediaType.equals(mediaType);
} }
@Override public int hashCode() { @Override public int hashCode() {

View File

@@ -19,6 +19,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okio.Buffer; import okio.Buffer;
import okio.BufferedSink; import okio.BufferedSink;
@@ -119,7 +120,8 @@ public final class MultipartBody extends RequestBody {
* to awkward operations like measuring the encoded length of header strings, or the * to awkward operations like measuring the encoded length of header strings, or the
* length-in-digits of an encoded integer. * length-in-digits of an encoded integer.
*/ */
private long writeOrCountBytes(BufferedSink sink, boolean countBytes) throws IOException { private long writeOrCountBytes(
@Nullable BufferedSink sink, boolean countBytes) throws IOException {
long byteCount = 0L; long byteCount = 0L;
Buffer byteCountBuffer = null; Buffer byteCountBuffer = null;
@@ -225,7 +227,7 @@ public final class MultipartBody extends RequestBody {
return create(null, body); return create(null, body);
} }
public static Part create(Headers headers, RequestBody body) { public static Part create(@Nullable Headers headers, RequestBody body) {
if (body == null) { if (body == null) {
throw new NullPointerException("body == null"); throw new NullPointerException("body == null");
} }
@@ -242,7 +244,7 @@ public final class MultipartBody extends RequestBody {
return createFormData(name, null, RequestBody.create(null, value)); return createFormData(name, null, RequestBody.create(null, value));
} }
public static Part createFormData(String name, String filename, RequestBody body) { public static Part createFormData(String name, @Nullable String filename, RequestBody body) {
if (name == null) { if (name == null) {
throw new NullPointerException("name == null"); throw new NullPointerException("name == null");
} }
@@ -257,15 +259,15 @@ public final class MultipartBody extends RequestBody {
return create(Headers.of("Content-Disposition", disposition.toString()), body); return create(Headers.of("Content-Disposition", disposition.toString()), body);
} }
final Headers headers; final @Nullable Headers headers;
final RequestBody body; final RequestBody body;
private Part(Headers headers, RequestBody body) { private Part(@Nullable Headers headers, RequestBody body) {
this.headers = headers; this.headers = headers;
this.body = body; this.body = body;
} }
public Headers headers() { public @Nullable Headers headers() {
return headers; return headers;
} }
@@ -308,7 +310,7 @@ public final class MultipartBody extends RequestBody {
} }
/** Add a part to the body. */ /** Add a part to the body. */
public Builder addPart(Headers headers, RequestBody body) { public Builder addPart(@Nullable Headers headers, RequestBody body) {
return addPart(Part.create(headers, body)); return addPart(Part.create(headers, body));
} }
@@ -318,7 +320,7 @@ public final class MultipartBody extends RequestBody {
} }
/** Add a form data part to the body. */ /** Add a form data part to the body. */
public Builder addFormDataPart(String name, String filename, RequestBody body) { public Builder addFormDataPart(String name, @Nullable String filename, RequestBody body) {
return addPart(Part.createFormData(name, filename, body)); return addPart(Part.createFormData(name, filename, body));
} }

View File

@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
@@ -191,7 +192,7 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory
} }
final Dispatcher dispatcher; final Dispatcher dispatcher;
final Proxy proxy; final @Nullable Proxy proxy;
final List<Protocol> protocols; final List<Protocol> protocols;
final List<ConnectionSpec> connectionSpecs; final List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors; final List<Interceptor> interceptors;
@@ -199,11 +200,11 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory
final EventListener.Factory eventListenerFactory; final EventListener.Factory eventListenerFactory;
final ProxySelector proxySelector; final ProxySelector proxySelector;
final CookieJar cookieJar; final CookieJar cookieJar;
final Cache cache; final @Nullable Cache cache;
final InternalCache internalCache; final @Nullable InternalCache internalCache;
final SocketFactory socketFactory; final SocketFactory socketFactory;
final SSLSocketFactory sslSocketFactory; final @Nullable SSLSocketFactory sslSocketFactory;
final CertificateChainCleaner certificateChainCleaner; final @Nullable CertificateChainCleaner certificateChainCleaner;
final HostnameVerifier hostnameVerifier; final HostnameVerifier hostnameVerifier;
final CertificatePinner certificatePinner; final CertificatePinner certificatePinner;
final Authenticator proxyAuthenticator; final Authenticator proxyAuthenticator;
@@ -433,7 +434,7 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory
public static final class Builder { public static final class Builder {
Dispatcher dispatcher; Dispatcher dispatcher;
Proxy proxy; @Nullable Proxy proxy;
List<Protocol> protocols; List<Protocol> protocols;
List<ConnectionSpec> connectionSpecs; List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors = new ArrayList<>(); final List<Interceptor> interceptors = new ArrayList<>();
@@ -441,11 +442,11 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory
EventListener.Factory eventListenerFactory; EventListener.Factory eventListenerFactory;
ProxySelector proxySelector; ProxySelector proxySelector;
CookieJar cookieJar; CookieJar cookieJar;
Cache cache; @Nullable Cache cache;
InternalCache internalCache; @Nullable InternalCache internalCache;
SocketFactory socketFactory; SocketFactory socketFactory;
SSLSocketFactory sslSocketFactory; @Nullable SSLSocketFactory sslSocketFactory;
CertificateChainCleaner certificateChainCleaner; @Nullable CertificateChainCleaner certificateChainCleaner;
HostnameVerifier hostnameVerifier; HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner; CertificatePinner certificatePinner;
Authenticator proxyAuthenticator; Authenticator proxyAuthenticator;
@@ -568,7 +569,7 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory
* precedence over {@link #proxySelector}, which is only honored when this proxy is null (which * precedence over {@link #proxySelector}, which is only honored when this proxy is null (which
* it is by default). To disable proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}. * it is by default). To disable proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}.
*/ */
public Builder proxy(Proxy proxy) { public Builder proxy(@Nullable Proxy proxy) {
this.proxy = proxy; this.proxy = proxy;
return this; return this;
} }
@@ -599,13 +600,13 @@ public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory
} }
/** Sets the response cache to be used to read and write cached responses. */ /** Sets the response cache to be used to read and write cached responses. */
void setInternalCache(InternalCache internalCache) { void setInternalCache(@Nullable InternalCache internalCache) {
this.internalCache = internalCache; this.internalCache = internalCache;
this.cache = null; this.cache = null;
} }
/** Sets the response cache to be used to read and write cached responses. */ /** Sets the response cache to be used to read and write cached responses. */
public Builder cache(Cache cache) { public Builder cache(@Nullable Cache cache) {
this.cache = cache; this.cache = cache;
this.internalCache = null; this.internalCache = null;
return this; return this;

View File

@@ -17,6 +17,7 @@ package okhttp3;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.http.HttpMethod; import okhttp3.internal.http.HttpMethod;
@@ -28,7 +29,7 @@ public final class Request {
final HttpUrl url; final HttpUrl url;
final String method; final String method;
final Headers headers; final Headers headers;
final RequestBody body; final @Nullable RequestBody body;
final Object tag; final Object tag;
private volatile CacheControl cacheControl; // Lazily initialized. private volatile CacheControl cacheControl; // Lazily initialized.
@@ -61,7 +62,7 @@ public final class Request {
return headers.values(name); return headers.values(name);
} }
public RequestBody body() { public @Nullable RequestBody body() {
return body; return body;
} }
@@ -211,7 +212,7 @@ public final class Request {
return method("POST", body); return method("POST", body);
} }
public Builder delete(RequestBody body) { public Builder delete(@Nullable RequestBody body) {
return method("DELETE", body); return method("DELETE", body);
} }
@@ -227,7 +228,7 @@ public final class Request {
return method("PATCH", body); return method("PATCH", body);
} }
public Builder method(String method, RequestBody body) { public Builder method(String method, @Nullable RequestBody body) {
if (method == null) throw new NullPointerException("method == null"); if (method == null) throw new NullPointerException("method == null");
if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0"); if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0");
if (body != null && !HttpMethod.permitsRequestBody(method)) { if (body != null && !HttpMethod.permitsRequestBody(method)) {

View File

@@ -18,6 +18,7 @@ package okhttp3;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okio.BufferedSink; import okio.BufferedSink;
import okio.ByteString; import okio.ByteString;
@@ -26,7 +27,7 @@ import okio.Source;
public abstract class RequestBody { public abstract class RequestBody {
/** Returns the Content-Type header for this body. */ /** Returns the Content-Type header for this body. */
public abstract MediaType contentType(); public abstract @Nullable MediaType contentType();
/** /**
* Returns the number of bytes that will be written to {@code out} in a call to {@link #writeTo}, * Returns the number of bytes that will be written to {@code out} in a call to {@link #writeTo},
@@ -43,7 +44,7 @@ public abstract class RequestBody {
* Returns a new request body that transmits {@code content}. If {@code contentType} is non-null * Returns a new request body that transmits {@code content}. If {@code contentType} is non-null
* and lacks a charset, this will use UTF-8. * and lacks a charset, this will use UTF-8.
*/ */
public static RequestBody create(MediaType contentType, String content) { public static RequestBody create(@Nullable MediaType contentType, String content) {
Charset charset = Util.UTF_8; Charset charset = Util.UTF_8;
if (contentType != null) { if (contentType != null) {
charset = contentType.charset(); charset = contentType.charset();
@@ -57,9 +58,10 @@ public abstract class RequestBody {
} }
/** Returns a new request body that transmits {@code content}. */ /** Returns a new request body that transmits {@code content}. */
public static RequestBody create(final MediaType contentType, final ByteString content) { public static RequestBody create(
final @Nullable MediaType contentType, final ByteString content) {
return new RequestBody() { return new RequestBody() {
@Override public MediaType contentType() { @Override public @Nullable MediaType contentType() {
return contentType; return contentType;
} }
@@ -74,17 +76,17 @@ public abstract class RequestBody {
} }
/** Returns a new request body that transmits {@code content}. */ /** Returns a new request body that transmits {@code content}. */
public static RequestBody create(final MediaType contentType, final byte[] content) { public static RequestBody create(final @Nullable MediaType contentType, final byte[] content) {
return create(contentType, content, 0, content.length); return create(contentType, content, 0, content.length);
} }
/** Returns a new request body that transmits {@code content}. */ /** Returns a new request body that transmits {@code content}. */
public static RequestBody create(final MediaType contentType, final byte[] content, public static RequestBody create(final @Nullable MediaType contentType, final byte[] content,
final int offset, final int byteCount) { final int offset, final int byteCount) {
if (content == null) throw new NullPointerException("content == null"); if (content == null) throw new NullPointerException("content == null");
Util.checkOffsetAndCount(content.length, offset, byteCount); Util.checkOffsetAndCount(content.length, offset, byteCount);
return new RequestBody() { return new RequestBody() {
@Override public MediaType contentType() { @Override public @Nullable MediaType contentType() {
return contentType; return contentType;
} }
@@ -99,11 +101,11 @@ public abstract class RequestBody {
} }
/** Returns a new request body that transmits the content of {@code file}. */ /** Returns a new request body that transmits the content of {@code file}. */
public static RequestBody create(final MediaType contentType, final File file) { public static RequestBody create(final @Nullable MediaType contentType, final File file) {
if (file == null) throw new NullPointerException("content == null"); if (file == null) throw new NullPointerException("content == null");
return new RequestBody() { return new RequestBody() {
@Override public MediaType contentType() { @Override public @Nullable MediaType contentType() {
return contentType; return contentType;
} }

View File

@@ -19,6 +19,7 @@ import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import okhttp3.internal.http.HttpHeaders; import okhttp3.internal.http.HttpHeaders;
import okio.Buffer; import okio.Buffer;
import okio.BufferedSource; import okio.BufferedSource;
@@ -44,12 +45,12 @@ public final class Response implements Closeable {
final Protocol protocol; final Protocol protocol;
final int code; final int code;
final String message; final String message;
final Handshake handshake; final @Nullable Handshake handshake;
final Headers headers; final Headers headers;
final ResponseBody body; final @Nullable ResponseBody body;
final Response networkResponse; final @Nullable Response networkResponse;
final Response cacheResponse; final @Nullable Response cacheResponse;
final Response priorResponse; final @Nullable Response priorResponse;
final long sentRequestAtMillis; final long sentRequestAtMillis;
final long receivedResponseAtMillis; final long receivedResponseAtMillis;
@@ -122,11 +123,11 @@ public final class Response implements Closeable {
return headers.values(name); return headers.values(name);
} }
public String header(String name) { public @Nullable String header(String name) {
return header(name, null); return header(name, null);
} }
public String header(String name, String defaultValue) { public @Nullable String header(String name, @Nullable String defaultValue) {
String result = headers.get(name); String result = headers.get(name);
return result != null ? result : defaultValue; return result != null ? result : defaultValue;
} }
@@ -172,7 +173,7 @@ public final class Response implements Closeable {
* <p>This always returns null on responses returned from {@link #cacheResponse}, {@link * <p>This always returns null on responses returned from {@link #cacheResponse}, {@link
* #networkResponse}, and {@link #priorResponse()}. * #networkResponse}, and {@link #priorResponse()}.
*/ */
public ResponseBody body() { public @Nullable ResponseBody body() {
return body; return body;
} }
@@ -200,7 +201,7 @@ public final class Response implements Closeable {
* the network, such as when the response is fully cached. The body of the returned response * the network, such as when the response is fully cached. The body of the returned response
* should not be read. * should not be read.
*/ */
public Response networkResponse() { public @Nullable Response networkResponse() {
return networkResponse; return networkResponse;
} }
@@ -209,7 +210,7 @@ public final class Response implements Closeable {
* cache. For conditional get requests the cache response and network response may both be * cache. For conditional get requests the cache response and network response may both be
* non-null. The body of the returned response should not be read. * non-null. The body of the returned response should not be read.
*/ */
public Response cacheResponse() { public @Nullable Response cacheResponse() {
return cacheResponse; return cacheResponse;
} }
@@ -219,7 +220,7 @@ public final class Response implements Closeable {
* returned response should not be read because it has already been consumed by the redirecting * returned response should not be read because it has already been consumed by the redirecting
* client. * client.
*/ */
public Response priorResponse() { public @Nullable Response priorResponse() {
return priorResponse; return priorResponse;
} }
@@ -290,7 +291,7 @@ public final class Response implements Closeable {
Protocol protocol; Protocol protocol;
int code = -1; int code = -1;
String message; String message;
Handshake handshake; @Nullable Handshake handshake;
Headers.Builder headers; Headers.Builder headers;
ResponseBody body; ResponseBody body;
Response networkResponse; Response networkResponse;
@@ -338,7 +339,7 @@ public final class Response implements Closeable {
return this; return this;
} }
public Builder handshake(Handshake handshake) { public Builder handshake(@Nullable Handshake handshake) {
this.handshake = handshake; this.handshake = handshake;
return this; return this;
} }
@@ -372,18 +373,18 @@ public final class Response implements Closeable {
return this; return this;
} }
public Builder body(ResponseBody body) { public Builder body(@Nullable ResponseBody body) {
this.body = body; this.body = body;
return this; return this;
} }
public Builder networkResponse(Response networkResponse) { public Builder networkResponse(@Nullable Response networkResponse) {
if (networkResponse != null) checkSupportResponse("networkResponse", networkResponse); if (networkResponse != null) checkSupportResponse("networkResponse", networkResponse);
this.networkResponse = networkResponse; this.networkResponse = networkResponse;
return this; return this;
} }
public Builder cacheResponse(Response cacheResponse) { public Builder cacheResponse(@Nullable Response cacheResponse) {
if (cacheResponse != null) checkSupportResponse("cacheResponse", cacheResponse); if (cacheResponse != null) checkSupportResponse("cacheResponse", cacheResponse);
this.cacheResponse = cacheResponse; this.cacheResponse = cacheResponse;
return this; return this;
@@ -401,7 +402,7 @@ public final class Response implements Closeable {
} }
} }
public Builder priorResponse(Response priorResponse) { public Builder priorResponse(@Nullable Response priorResponse) {
if (priorResponse != null) checkPriorResponse(priorResponse); if (priorResponse != null) checkPriorResponse(priorResponse);
this.priorResponse = priorResponse; this.priorResponse = priorResponse;
return this; return this;

View File

@@ -21,6 +21,7 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okio.Buffer; import okio.Buffer;
import okio.BufferedSource; import okio.BufferedSource;
@@ -102,7 +103,7 @@ public abstract class ResponseBody implements Closeable {
/** Multiple calls to {@link #charStream()} must return the same instance. */ /** Multiple calls to {@link #charStream()} must return the same instance. */
private Reader reader; private Reader reader;
public abstract MediaType contentType(); public abstract @Nullable MediaType contentType();
/** /**
* Returns the number of bytes in that will returned by {@link #bytes}, or {@link #byteStream}, or * Returns the number of bytes in that will returned by {@link #bytes}, or {@link #byteStream}, or
@@ -190,7 +191,7 @@ public abstract class ResponseBody implements Closeable {
* Returns a new response body that transmits {@code content}. If {@code contentType} is non-null * Returns a new response body that transmits {@code content}. If {@code contentType} is non-null
* and lacks a charset, this will use UTF-8. * and lacks a charset, this will use UTF-8.
*/ */
public static ResponseBody create(MediaType contentType, String content) { public static ResponseBody create(@Nullable MediaType contentType, String content) {
Charset charset = UTF_8; Charset charset = UTF_8;
if (contentType != null) { if (contentType != null) {
charset = contentType.charset(); charset = contentType.charset();
@@ -204,17 +205,17 @@ public abstract class ResponseBody implements Closeable {
} }
/** Returns a new response body that transmits {@code content}. */ /** Returns a new response body that transmits {@code content}. */
public static ResponseBody create(final MediaType contentType, byte[] content) { public static ResponseBody create(final @Nullable MediaType contentType, byte[] content) {
Buffer buffer = new Buffer().write(content); Buffer buffer = new Buffer().write(content);
return create(contentType, content.length, buffer); return create(contentType, content.length, buffer);
} }
/** Returns a new response body that transmits {@code content}. */ /** Returns a new response body that transmits {@code content}. */
public static ResponseBody create( public static ResponseBody create(final @Nullable MediaType contentType,
final MediaType contentType, final long contentLength, final BufferedSource content) { final long contentLength, final BufferedSource content) {
if (content == null) throw new NullPointerException("source == null"); if (content == null) throw new NullPointerException("source == null");
return new ResponseBody() { return new ResponseBody() {
@Override public MediaType contentType() { @Override public @Nullable MediaType contentType() {
return contentType; return contentType;
} }

View File

@@ -17,6 +17,7 @@ package okhttp3;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Proxy; import java.net.Proxy;
import javax.annotation.Nullable;
/** /**
* The concrete route used by a connection to reach an abstract origin server. When creating a * The concrete route used by a connection to reach an abstract origin server. When creating a
@@ -79,14 +80,11 @@ public final class Route {
return address.sslSocketFactory != null && proxy.type() == Proxy.Type.HTTP; return address.sslSocketFactory != null && proxy.type() == Proxy.Type.HTTP;
} }
@Override public boolean equals(Object obj) { @Override public boolean equals(@Nullable Object other) {
if (obj instanceof Route) { return other instanceof Route
Route other = (Route) obj; && ((Route) other).address.equals(address)
return address.equals(other.address) && ((Route) other).proxy.equals(proxy)
&& proxy.equals(other.proxy) && ((Route) other).inetSocketAddress.equals(inetSocketAddress);
&& inetSocketAddress.equals(other.inetSocketAddress);
}
return false;
} }
@Override public int hashCode() { @Override public int hashCode() {

View File

@@ -15,6 +15,7 @@
*/ */
package okhttp3; package okhttp3;
import javax.annotation.Nullable;
import okio.ByteString; import okio.ByteString;
/** /**
@@ -101,7 +102,7 @@ public interface WebSocket {
* href="http://tools.ietf.org/html/rfc6455#section-7.4">Section 7.4 of RFC 6455</a> or {@code 0}. * href="http://tools.ietf.org/html/rfc6455#section-7.4">Section 7.4 of RFC 6455</a> or {@code 0}.
* @param reason Reason for shutting down or {@code null}. * @param reason Reason for shutting down or {@code null}.
*/ */
boolean close(int code, String reason); boolean close(int code, @Nullable String reason);
/** /**
* Immediately and violently release resources held by this web socket, discarding any enqueued * Immediately and violently release resources held by this web socket, discarding any enqueued

View File

@@ -16,6 +16,7 @@
package okhttp3.internal.cache; package okhttp3.internal.cache;
import java.util.Date; import java.util.Date;
import javax.annotation.Nullable;
import okhttp3.CacheControl; import okhttp3.CacheControl;
import okhttp3.Headers; import okhttp3.Headers;
import okhttp3.Request; import okhttp3.Request;
@@ -48,10 +49,10 @@ import static java.util.concurrent.TimeUnit.SECONDS;
*/ */
public final class CacheStrategy { public final class CacheStrategy {
/** The request to send on the network, or null if this call doesn't use the network. */ /** The request to send on the network, or null if this call doesn't use the network. */
public final Request networkRequest; public final @Nullable Request networkRequest;
/** The cached response to return or validate; or null if this call doesn't use a cache. */ /** The cached response to return or validate; or null if this call doesn't use a cache. */
public final Response cacheResponse; public final @Nullable Response cacheResponse;
CacheStrategy(Request networkRequest, Response cacheResponse) { CacheStrategy(Request networkRequest, Response cacheResponse) {
this.networkRequest = networkRequest; this.networkRequest = networkRequest;

View File

@@ -32,6 +32,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Nullable;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.io.FileSystem; import okhttp3.internal.io.FileSystem;
import okhttp3.internal.platform.Platform; import okhttp3.internal.platform.Platform;
@@ -454,7 +455,7 @@ public final class DiskLruCache implements Closeable, Flushable {
/** /**
* Returns an editor for the entry named {@code key}, or null if another edit is in progress. * Returns an editor for the entry named {@code key}, or null if another edit is in progress.
*/ */
public Editor edit(String key) throws IOException { public @Nullable Editor edit(String key) throws IOException {
return edit(key, ANY_SEQUENCE_NUMBER); return edit(key, ANY_SEQUENCE_NUMBER);
} }
@@ -805,7 +806,7 @@ public final class DiskLruCache implements Closeable, Flushable {
* Returns an editor for this snapshot's entry, or null if either the entry has changed since * Returns an editor for this snapshot's entry, or null if either the entry has changed since
* this snapshot was created or if another edit is in progress. * this snapshot was created or if another edit is in progress.
*/ */
public Editor edit() throws IOException { public @Nullable Editor edit() throws IOException {
return DiskLruCache.this.edit(key, sequenceNumber); return DiskLruCache.this.edit(key, sequenceNumber);
} }

View File

@@ -29,6 +29,7 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
@@ -378,7 +379,7 @@ public final class RealConnection extends Http2Connection.Listener implements Co
* Returns true if this connection can carry a stream allocation to {@code address}. If non-null * Returns true if this connection can carry a stream allocation to {@code address}. If non-null
* {@code route} is the resolved route for a connection. * {@code route} is the resolved route for a connection.
*/ */
public boolean isEligible(Address address, Route route) { public boolean isEligible(Address address, @Nullable Route route) {
// If this connection is not accepting new streams, we're done. // If this connection is not accepting new streams, we're done.
if (allocations.size() >= allocationLimit || noNewStreams) return false; if (allocations.size() >= allocationLimit || noNewStreams) return false;

View File

@@ -0,0 +1,3 @@
/** An HTTP+HTTP/2 client for Android and Java applications. */
@javax.annotation.ParametersAreNonnullByDefault
package okhttp3;

View File

@@ -87,6 +87,12 @@
<artifactId>okio</artifactId> <artifactId>okio</artifactId>
<version>${okio.version}</version> <version>${okio.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>