diff --git a/core/src/main/java/com/dropbox/core/AccessErrorException.java b/core/src/main/java/com/dropbox/core/AccessErrorException.java index f46f757ac..e9a5f3bff 100644 --- a/core/src/main/java/com/dropbox/core/AccessErrorException.java +++ b/core/src/main/java/com/dropbox/core/AccessErrorException.java @@ -2,19 +2,24 @@ import com.dropbox.core.v2.auth.AccessError; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Gets thrown when invalid access occurs. */ public class AccessErrorException extends DbxException { private static final long serialVersionUID = 0; - private final AccessError accessError; + private final @Nonnull AccessError accessError; - public AccessError getAccessError() { + public @Nonnull AccessError getAccessError() { return accessError; } - public AccessErrorException(String requestId, String message, AccessError accessError) { + public AccessErrorException(@Nullable String requestId, + @Nullable String message, + @Nonnull AccessError accessError) { super(requestId, message); this.accessError = accessError; } diff --git a/core/src/main/java/com/dropbox/core/ApiErrorResponse.java b/core/src/main/java/com/dropbox/core/ApiErrorResponse.java index 701a8106d..6060a97a2 100644 --- a/core/src/main/java/com/dropbox/core/ApiErrorResponse.java +++ b/core/src/main/java/com/dropbox/core/ApiErrorResponse.java @@ -10,11 +10,14 @@ import com.dropbox.core.stone.StoneSerializer; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + final class ApiErrorResponse { - private final T error; - private LocalizedText userMessage; + private final @Nonnull T error; + private @Nullable LocalizedText userMessage; - public ApiErrorResponse(T error, LocalizedText userMessage) { + public ApiErrorResponse(@Nonnull T error, @Nullable LocalizedText userMessage) { if (error == null) { throw new NullPointerException("error"); } @@ -22,11 +25,11 @@ public ApiErrorResponse(T error, LocalizedText userMessage) { this.userMessage = userMessage; } - public T getError() { + public @Nonnull T getError() { return error; } - public LocalizedText getUserMessage() { + public @Nullable LocalizedText getUserMessage() { return userMessage; } @@ -34,19 +37,19 @@ public LocalizedText getUserMessage() { * For internal use only. */ static final class Serializer extends StoneSerializer> { - private StoneSerializer errSerializer; + private @Nonnull StoneSerializer errSerializer; - public Serializer(StoneSerializer errSerializer) { + public Serializer(@Nonnull StoneSerializer errSerializer) { this.errSerializer = errSerializer; } @Override - public void serialize(ApiErrorResponse value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nonnull ApiErrorResponse value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { throw new UnsupportedOperationException("Error wrapper serialization not supported."); } @Override - public ApiErrorResponse deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull ApiErrorResponse deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { T error = null; LocalizedText userMessage = null; @@ -73,4 +76,3 @@ public ApiErrorResponse deserialize(JsonParser p) throws IOException, JsonPar } } } - diff --git a/core/src/main/java/com/dropbox/core/BadRequestException.java b/core/src/main/java/com/dropbox/core/BadRequestException.java index 2aa27f641..4c0d1640d 100644 --- a/core/src/main/java/com/dropbox/core/BadRequestException.java +++ b/core/src/main/java/com/dropbox/core/BadRequestException.java @@ -1,5 +1,8 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * This is what is thrown when the Dropbox server tells us that it didn't like something about our * request. This corresponds to the HTTP 400 status code. @@ -7,7 +10,7 @@ public class BadRequestException extends ProtocolException { private static final long serialVersionUID = 0; - public BadRequestException(String requestId, String message) { + public BadRequestException(@Nullable String requestId, @Nullable String message) { super(requestId, message); } } diff --git a/core/src/main/java/com/dropbox/core/BadResponseCodeException.java b/core/src/main/java/com/dropbox/core/BadResponseCodeException.java index 652bb941b..5b58aa9e7 100644 --- a/core/src/main/java/com/dropbox/core/BadResponseCodeException.java +++ b/core/src/main/java/com/dropbox/core/BadResponseCodeException.java @@ -1,5 +1,8 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Thrown when the Dropbox server responds with an HTTP status code we didn't expect. */ @@ -8,12 +11,15 @@ public class BadResponseCodeException extends BadResponseException { private final int statusCode; - public BadResponseCodeException(String requestId, String message, int statusCode) { + public BadResponseCodeException(@Nullable String requestId, @Nullable String message, int statusCode) { super(requestId, message); this.statusCode = statusCode; } - public BadResponseCodeException(String requestId, String message, int statusCode, Throwable cause) { + public BadResponseCodeException(@Nullable String requestId, + @Nullable String message, + int statusCode, + @Nonnull Throwable cause) { super(requestId, message, cause); this.statusCode = statusCode; } @@ -27,4 +33,3 @@ public int getStatusCode() { return statusCode; } } - diff --git a/core/src/main/java/com/dropbox/core/BadResponseException.java b/core/src/main/java/com/dropbox/core/BadResponseException.java index c29ad5ff8..7daa29e5b 100644 --- a/core/src/main/java/com/dropbox/core/BadResponseException.java +++ b/core/src/main/java/com/dropbox/core/BadResponseException.java @@ -1,5 +1,8 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Thrown when we the response from the Dropbox server isn't something we expect. * For example, if the JSON returned by the server is malformed or missing fields. @@ -7,12 +10,11 @@ public class BadResponseException extends ProtocolException { private static final long serialVersionUID = 0; - public BadResponseException(String requestId, String message) { + public BadResponseException(@Nullable String requestId, @Nullable String message) { super(requestId, message); } - public BadResponseException(String requestId, String message, Throwable cause) { + public BadResponseException(@Nullable String requestId, @Nullable String message, @Nonnull Throwable cause) { super(requestId, message, cause); } } - diff --git a/core/src/main/java/com/dropbox/core/DbxApiException.java b/core/src/main/java/com/dropbox/core/DbxApiException.java index 2b96328e2..01a624b46 100644 --- a/core/src/main/java/com/dropbox/core/DbxApiException.java +++ b/core/src/main/java/com/dropbox/core/DbxApiException.java @@ -1,5 +1,6 @@ package com.dropbox.core; +import javax.annotation.Nonnull; import javax.annotation.Nullable; /** @@ -8,14 +9,19 @@ public class DbxApiException extends DbxException { private static final long serialVersionUID = 0L; - private final LocalizedText userMessage; + private final @Nullable LocalizedText userMessage; - public DbxApiException(String requestId, LocalizedText userMessage, String message) { + public DbxApiException(@Nullable String requestId, + @Nullable LocalizedText userMessage, + @Nonnull String message) { super(requestId, message); this.userMessage = userMessage; } - public DbxApiException(String requestId, LocalizedText userMessage, String message, Throwable cause) { + public DbxApiException(@Nullable String requestId, + @Nullable LocalizedText userMessage, + @Nonnull String message, + @Nonnull Throwable cause) { super(requestId, message, cause); this.userMessage = userMessage; } @@ -27,16 +33,17 @@ public DbxApiException(String requestId, LocalizedText userMessage, String messa * * @return human-readable message to display to end user, or {@code null} if unavailable */ - @Nullable - public LocalizedText getUserMessage() { + public @Nullable LocalizedText getUserMessage() { return userMessage; } - protected static String buildMessage(String routeName, LocalizedText userMessage) { + protected static @Nonnull String buildMessage(@Nonnull String routeName, @Nullable LocalizedText userMessage) { return buildMessage(routeName, userMessage, null); } - protected static String buildMessage(String routeName, LocalizedText userMessage, Object errorValue) { + protected static @Nonnull String buildMessage(@Nonnull String routeName, + @Nullable LocalizedText userMessage, + @Nullable Object errorValue) { StringBuilder sb = new StringBuilder(); sb.append("Exception in ").append(routeName); if (errorValue != null) { diff --git a/core/src/main/java/com/dropbox/core/DbxAppInfo.java b/core/src/main/java/com/dropbox/core/DbxAppInfo.java index 4183e2e80..6b715b60b 100644 --- a/core/src/main/java/com/dropbox/core/DbxAppInfo.java +++ b/core/src/main/java/com/dropbox/core/DbxAppInfo.java @@ -1,5 +1,7 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import static com.dropbox.core.util.StringUtil.jq; @@ -13,15 +15,14 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -/*>>> import checkers.nullness.quals.Nullable; */ /** * Identifying information about your application. */ public class DbxAppInfo extends Dumpable { - private final String key; - private final String secret; - private final DbxHost host; + private final @Nonnull String key; + private final @Nullable String secret; + private final @Nonnull DbxHost host; /** * @@ -30,7 +31,7 @@ public class DbxAppInfo extends Dumpable { * @param key Dropbox app key (see {@link #getKey}) * @see com.dropbox.core.DbxPKCEWebAuth */ - public DbxAppInfo(String key) { + public DbxAppInfo(@Nonnull String key) { this(key, null); } @@ -38,7 +39,7 @@ public DbxAppInfo(String key) { * @param key Dropbox app key (see {@link #getKey}) * @param secret Dropbox app secret (see {@link #getSecret}) */ - public DbxAppInfo(String key, String secret) { + public DbxAppInfo(@Nonnull String key, @Nullable String secret) { checkKeyArg(key); checkSecretArg(secret); @@ -52,7 +53,7 @@ public DbxAppInfo(String key, String secret) { * @param secret Dropbox app secret (see {@link #getSecret}) * @param host Dropbox host configuration (see {@link #getHost}) */ - public DbxAppInfo(String key, String secret, DbxHost host) { + public DbxAppInfo(@Nonnull String key, @Nullable String secret, @Nonnull DbxHost host) { checkKeyArg(key); checkSecretArg(secret); @@ -68,7 +69,7 @@ public DbxAppInfo(String key, String secret, DbxHost host) { * * @return Dropbox app key */ - public String getKey() { + public @Nonnull String getKey() { return key; } @@ -83,7 +84,7 @@ public String getKey() { * * @return Dropbox app secret */ - public String getSecret() { + public @Nullable String getSecret() { return secret; } @@ -95,7 +96,7 @@ public String getSecret() { * * @return Dropbox host configuration */ - public DbxHost getHost() { + public @Nonnull DbxHost getHost() { return host; } @@ -110,7 +111,7 @@ public boolean hasSecret() { } @Override - protected void dumpFields(DumpWriter out) { + protected void dumpFields(@Nonnull DumpWriter out) { out.f("key").v(key); out.f("secret").v(secret); } @@ -125,7 +126,7 @@ protected void dumpFields(DumpWriter out) { * that what you passed in is an actual valid Dropbox API app key. *

*/ - public static /*@Nullable*/String getKeyFormatError(String key) { + public static @Nullable String getKeyFormatError(@Nullable String key) { return getTokenPartError(key); } @@ -139,17 +140,17 @@ protected void dumpFields(DumpWriter out) { * you passed in is an actual valid Dropbox API app key. *

*/ - public static /*@Nullable*/String getSecretFormatError(String key) { + public static @Nullable String getSecretFormatError(@Nullable String key) { return getTokenPartError(key); } // ------------------------------------------------------ // JSON parsing - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public final DbxAppInfo read(JsonParser parser) + public final @Nonnull DbxAppInfo read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -191,10 +192,10 @@ else if (fieldName.equals("host")) { } }; - public static final JsonReader KeyReader = new JsonReader() + public static final @Nonnull JsonReader KeyReader = new JsonReader() { @Override - public String read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull String read(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { String v = parser.getText(); @@ -211,10 +212,10 @@ public String read(JsonParser parser) throws IOException, JsonReadException } }; - public static final JsonReader SecretReader = new JsonReader() + public static final @Nonnull JsonReader SecretReader = new JsonReader() { @Override - public String read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull String read(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { String v = parser.getText(); @@ -232,7 +233,7 @@ public String read(JsonParser parser) throws IOException, JsonReadException }; - public static /*@Nullable*/String getTokenPartError(String s) + public static @Nullable String getTokenPartError(@Nullable String s) { if (s == null) return null; if (s.length() == 0) return "can't be empty"; @@ -246,7 +247,7 @@ public String read(JsonParser parser) throws IOException, JsonReadException return null; } - public static void checkKeyArg(String key) + public static void checkKeyArg(@Nullable String key) { String error; @@ -260,7 +261,7 @@ public static void checkKeyArg(String key) throw new IllegalArgumentException("Bad 'key': " + error); } - public static void checkSecretArg(String secret) + public static void checkSecretArg(@Nullable String secret) { String error = getTokenPartError(secret); if (error == null) return; diff --git a/core/src/main/java/com/dropbox/core/DbxAuthFinish.java b/core/src/main/java/com/dropbox/core/DbxAuthFinish.java index 6a661e0b7..4eebe0124 100644 --- a/core/src/main/java/com/dropbox/core/DbxAuthFinish.java +++ b/core/src/main/java/com/dropbox/core/DbxAuthFinish.java @@ -1,5 +1,7 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.json.JsonReadException; import com.dropbox.core.json.JsonReader; import com.fasterxml.jackson.core.JsonLocation; @@ -11,22 +13,21 @@ import static com.dropbox.core.util.StringUtil.jq; -/*>>> import checkers.nullness.quals.Nullable; */ /** * When you successfully complete the authorization process, the Dropbox server returns * this information to you. */ public final class DbxAuthFinish { - private final String accessToken; - private final Long expiresIn; - private final String refreshToken; - private final String userId; - private final String accountId; - private final String teamId; - private final /*@Nullable*/String urlState; + private final @Nonnull String accessToken; + private final @Nullable Long expiresIn; + private final @Nullable String refreshToken; + private final @Nonnull String userId; + private final @Nullable String accountId; + private final @Nullable String teamId; + private final @Nullable String urlState; private long issueTime; - private final String scope; + private final @Nullable String scope; /** * @param accessToken OAuth access token @@ -35,7 +36,11 @@ public final class DbxAuthFinish { * was passed */ @Deprecated - public DbxAuthFinish(String accessToken, String userId, String accountId, String teamId, /*@Nullable*/String urlState) { + public DbxAuthFinish(@Nonnull String accessToken, + @Nonnull String userId, + @Nullable String accountId, + @Nullable String teamId, + @Nullable String urlState) { this(accessToken, null, null, userId, teamId, accountId, urlState); } @@ -52,8 +57,13 @@ public DbxAuthFinish(String accessToken, String userId, String accountId, String * @param urlState State data passed in to {@link DbxWebAuth#start} or {@code null} if no state * was passed */ - public DbxAuthFinish(String accessToken, Long expiresIn, String refreshToken, String userId, - String teamId, String accountId, /*@Nullable*/String urlState) { + public DbxAuthFinish(@Nonnull String accessToken, + @Nullable Long expiresIn, + @Nullable String refreshToken, + @Nonnull String userId, + @Nullable String teamId, + @Nullable String accountId, + @Nullable String urlState) { this(accessToken, expiresIn, refreshToken, userId, teamId, accountId, urlState, null); } @@ -73,9 +83,14 @@ public DbxAuthFinish(String accessToken, Long expiresIn, String refreshToken, St * API endpoints. To call one API endpoint you have to obtains the scope first otherwise you * will get HTTP 401. */ - public DbxAuthFinish(String accessToken, Long expiresIn, String refreshToken, String userId, - String teamId, String accountId, /*@Nullable*/String urlState, String - scope) { + public DbxAuthFinish(@Nonnull String accessToken, + @Nullable Long expiresIn, + @Nullable String refreshToken, + @Nonnull String userId, + @Nullable String teamId, + @Nullable String accountId, + @Nullable String urlState, + @Nullable String scope) { this.accessToken = accessToken; this.expiresIn = expiresIn; this.refreshToken = refreshToken; @@ -93,7 +108,7 @@ public DbxAuthFinish(String accessToken, Long expiresIn, String refreshToken, St * * @return OAuth access token used for authorization with Dropbox servers */ - public String getAccessToken() { + public @Nonnull String getAccessToken() { return accessToken; } @@ -106,7 +121,7 @@ public String getAccessToken() { * * @return OAuth access token used for authorization with Dropbox servers */ - public Long getExpiresAt() { + public @Nullable Long getExpiresAt() { if (expiresIn == null) { return null; } @@ -122,7 +137,7 @@ public Long getExpiresAt() { * * @return OAuth access token used for authorization with Dropbox servers */ - public String getRefreshToken() { + public @Nullable String getRefreshToken() { return refreshToken; } @@ -132,7 +147,7 @@ public String getRefreshToken() { * * @return Dropbox user ID of user that approved your app for access to their account */ - public String getUserId() { + public @Nonnull String getUserId() { return userId; } @@ -142,7 +157,7 @@ public String getUserId() { * * @return Dropbox account ID of user that approved your app for access to their account */ - public String getAccountId() { + public @Nullable String getAccountId() { return accountId; } @@ -152,7 +167,7 @@ public String getAccountId() { * * @return Dropbox team ID of team's that approved your app for access to their account */ - public String getTeamId() { + public @Nullable String getTeamId() { return teamId; } @@ -164,7 +179,7 @@ public String getTeamId() { * API endpoints. To call one API endpoint you have to obtains the scope first otherwise you * will get HTTP 401. */ - public String getScope() { + public @Nullable String getScope() { return scope; } @@ -175,7 +190,7 @@ public String getScope() { * @return state data passed into {@link DbxWebAuth#start}, or {@code null} if no state was * passed */ - public /*@Nullable*/ String getUrlState() { + public @Nullable String getUrlState() { return urlState; } @@ -192,7 +207,8 @@ void setIssueTime(long issueTime) { * * @param urlState Custom state passed into /oauth2/authorize */ - DbxAuthFinish withUrlState(/*@Nullable*/ String urlState) { + @Nonnull + DbxAuthFinish withUrlState(@Nullable String urlState) { if (this.urlState != null) { throw new IllegalStateException("Already have URL state."); } @@ -207,8 +223,8 @@ DbxAuthFinish withUrlState(/*@Nullable*/ String urlState) { /** * For JSON parsing. */ - public static final JsonReader Reader = new JsonReader() { - public DbxAuthFinish read(JsonParser parser) throws IOException, JsonReadException { + public static final @Nonnull JsonReader Reader = new JsonReader() { + public @Nonnull DbxAuthFinish read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); String accessToken = null; @@ -281,9 +297,9 @@ else if (fieldName.equals("scope")) { } }; - public static final JsonReader BearerTokenTypeReader = new JsonReader() { + public static final @Nonnull JsonReader BearerTokenTypeReader = new JsonReader() { @Override - public String read(JsonParser parser) throws IOException, JsonReadException { + public @Nonnull String read(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { String v = parser.getText(); if (!v.equals("Bearer") && !v.equals("bearer")) { @@ -298,9 +314,9 @@ public String read(JsonParser parser) throws IOException, JsonReadException { }; - public static final JsonReader AccessTokenReader = new JsonReader() { + public static final @Nonnull JsonReader AccessTokenReader = new JsonReader() { @Override - public String read(JsonParser parser) throws IOException, JsonReadException { + public @Nonnull String read(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { String v = parser.getText(); String error = DbxAppInfo.getTokenPartError(v); diff --git a/core/src/main/java/com/dropbox/core/DbxAuthInfo.java b/core/src/main/java/com/dropbox/core/DbxAuthInfo.java index 7edb10185..e97c0ed9b 100644 --- a/core/src/main/java/com/dropbox/core/DbxAuthInfo.java +++ b/core/src/main/java/com/dropbox/core/DbxAuthInfo.java @@ -9,15 +9,17 @@ import com.fasterxml.jackson.core.JsonToken; import java.io.IOException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * Used by the example code to remember auth information. */ public final class DbxAuthInfo { - private final String accessToken; - private final Long expiresAt; - private final String refreshToken; - private final DbxHost host; + private final @Nonnull String accessToken; + private final @Nullable Long expiresAt; + private final @Nullable String refreshToken; + private final @Nonnull DbxHost host; /** * Creates a new instance with the given parameters. @@ -25,7 +27,7 @@ public final class DbxAuthInfo { * @param accessToken OAuth access token for authorization with Dropbox servers * @param host Dropbox host configuration used to select Dropbox servers */ - public DbxAuthInfo(String accessToken, DbxHost host) { + public DbxAuthInfo(@Nonnull String accessToken, @Nonnull DbxHost host) { this(accessToken, null, null, host); } @@ -38,7 +40,10 @@ public DbxAuthInfo(String accessToken, DbxHost host) { * @param refreshToken Refresh token which can bu used to obtain new accessToken * @param host Dropbox host configuration used to select Dropbox servers */ - public DbxAuthInfo(String accessToken, Long expiresAt, String refreshToken, DbxHost host) { + public DbxAuthInfo(@Nonnull String accessToken, + @Nullable Long expiresAt, + @Nullable String refreshToken, + @Nonnull DbxHost host) { if (accessToken == null) throw new IllegalArgumentException("'accessToken' can't be null"); if (host == null) throw new IllegalArgumentException("'host' can't be null"); @@ -53,7 +58,7 @@ public DbxAuthInfo(String accessToken, Long expiresAt, String refreshToken, DbxH * * @return OAuth access token */ - public String getAccessToken() { + public @Nonnull String getAccessToken() { return accessToken; } @@ -63,7 +68,7 @@ public String getAccessToken() { * * @return ExpiresAt in millisecond. */ - public Long getExpiresAt() { + public @Nullable Long getExpiresAt() { return expiresAt; } @@ -73,7 +78,7 @@ public Long getExpiresAt() { * * @return Refresh Token. */ - public String getRefreshToken() { + public @Nullable String getRefreshToken() { return refreshToken; } @@ -82,14 +87,14 @@ public String getRefreshToken() { * * @return Dropbox host configuration */ - public DbxHost getHost() { + public @Nonnull DbxHost getHost() { return host; } - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public final DbxAuthInfo read(JsonParser parser) + public final @Nonnull DbxAuthInfo read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -135,10 +140,10 @@ else if (fieldName.equals("access_token")) { } }; - public static final JsonWriter Writer = new JsonWriter() + public static final @Nonnull JsonWriter Writer = new JsonWriter() { @Override - public void write(DbxAuthInfo authInfo, JsonGenerator g) throws IOException + public void write(@Nonnull DbxAuthInfo authInfo, @Nonnull JsonGenerator g) throws IOException { g.writeStartObject(); g.writeStringField("access_token", authInfo.accessToken); diff --git a/core/src/main/java/com/dropbox/core/DbxDownloader.java b/core/src/main/java/com/dropbox/core/DbxDownloader.java index ac52113f0..e3d23dc8d 100644 --- a/core/src/main/java/com/dropbox/core/DbxDownloader.java +++ b/core/src/main/java/com/dropbox/core/DbxDownloader.java @@ -8,6 +8,9 @@ import java.io.IOException; import java.io.OutputStream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Class for handling download requests. * @@ -38,13 +41,13 @@ * */ public class DbxDownloader implements Closeable { - private final R result; - private final InputStream body; - private final String contentType; + private final @Nullable R result; + private final @Nonnull InputStream body; + private final @Nullable String contentType; private boolean closed; - public DbxDownloader(R result, InputStream body, String contentType) { + public DbxDownloader(@Nullable R result, @Nonnull InputStream body, @Nullable String contentType) { this.result = result; this.body = body; this.contentType = contentType; @@ -52,7 +55,7 @@ public DbxDownloader(R result, InputStream body, String contentType) { this.closed = false; } - public DbxDownloader(R result, InputStream body) { + public DbxDownloader(@Nullable R result, @Nonnull InputStream body) { this(result, body, null); } @@ -64,7 +67,7 @@ public DbxDownloader(R result, InputStream body) { * * @return Response from server */ - public R getResult() { + public @Nullable R getResult() { return result; } @@ -73,7 +76,7 @@ public R getResult() { * * @return the content type, or null if not known. */ - public String getContentType() { + public @Nullable String getContentType() { return contentType; } @@ -87,7 +90,7 @@ public String getContentType() { * * @throws IllegalStateException if this downloader has already been closed (see {@link #close}) */ - public InputStream getInputStream() { + public @Nonnull InputStream getInputStream() { assertOpen(); return body; } @@ -120,7 +123,7 @@ public InputStream getInputStream() { * @throws IOException if an error occurs writing the response body to the output stream. * @throws IllegalStateException if this downloader has already been closed (see {@link #close}) */ - public R download(OutputStream out) throws DbxException, IOException { + public @Nullable R download(@Nonnull OutputStream out) throws DbxException, IOException { try { IOUtil.copyStreamToStream(getInputStream(), out); } catch (IOUtil.WriteException ex) { @@ -146,7 +149,7 @@ public R download(OutputStream out) throws DbxException, IOException { * @throws DbxException if an error occurs reading the response or response body. * @throws IOException if an error occurs writing the response body to the output stream. */ - public R download(OutputStream out, IOUtil.ProgressListener progressListener) + public @Nullable R download(@Nonnull OutputStream out, @Nullable IOUtil.ProgressListener progressListener) throws DbxException, IOException { return download(new ProgressOutputStream(out, progressListener)); } diff --git a/core/src/main/java/com/dropbox/core/DbxException.java b/core/src/main/java/com/dropbox/core/DbxException.java index d485ab1c2..a98551b53 100644 --- a/core/src/main/java/com/dropbox/core/DbxException.java +++ b/core/src/main/java/com/dropbox/core/DbxException.java @@ -2,6 +2,9 @@ import java.io.IOException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * The base exception thrown by Dropbox API calls. Normally, you'll need to do something specific * for {@link InvalidAccessTokenException} and possibly for {@link RetryException}. The rest you @@ -10,22 +13,22 @@ public class DbxException extends Exception { private static final long serialVersionUID = 0L; - private final String requestId; + private final @Nullable String requestId; - public DbxException(String message) { + public DbxException(@Nullable String message) { this(null, message); } - public DbxException(String requestId, String message) { + public DbxException(@Nullable String requestId, @Nullable String message) { super(message); this.requestId = requestId; } - public DbxException(String message, Throwable cause) { + public DbxException(@Nullable String message, @Nonnull Throwable cause) { this(null, message, cause); } - public DbxException(String requestId, String message, Throwable cause) { + public DbxException(@Nullable String requestId, @Nullable String message, @Nonnull Throwable cause) { super(message, cause); this.requestId = requestId; } @@ -41,7 +44,7 @@ public DbxException(String requestId, String message, Throwable cause) { * @return unique ID associated with the request that caused this exception, or {@code null} if * one is not available. */ - public String getRequestId() { + public @Nullable String getRequestId() { return requestId; } } diff --git a/core/src/main/java/com/dropbox/core/DbxHost.java b/core/src/main/java/com/dropbox/core/DbxHost.java index 684d88233..77d9b7968 100644 --- a/core/src/main/java/com/dropbox/core/DbxHost.java +++ b/core/src/main/java/com/dropbox/core/DbxHost.java @@ -1,5 +1,7 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.json.JsonReadException; import com.dropbox.core.json.JsonReader; import com.dropbox.core.json.JsonWriter; @@ -11,7 +13,6 @@ import java.io.IOException; import java.util.Arrays; -/*>>> import checkers.nullness.quals.Nullable; */ /** * This is for mocking things out during testing. Most of the time you won't have to deal with @@ -22,17 +23,17 @@ public final class DbxHost { * The standard Dropbox hosts: "api.dropbox.com", "api-content.dropbox.com", * and "www.dropbox.com" */ - public static final DbxHost DEFAULT = new DbxHost( + public static final @Nonnull DbxHost DEFAULT = new DbxHost( "api.dropboxapi.com", "content.dropboxapi.com", "www.dropbox.com", "notify.dropboxapi.com" ); - private final String api; - private final String content; - private final String web; - private final String notify; + private final @Nonnull String api; + private final @Nonnull String content; + private final @Nonnull String web; + private final @Nonnull String notify; /** * @param api main Dropbox API server host name @@ -40,7 +41,7 @@ public final class DbxHost { * @param web Dropbox web server host name * @param notify Dropbox notification server host name */ - public DbxHost(String api, String content, String web, String notify) { + public DbxHost(@Nonnull String api, @Nonnull String content, @Nonnull String web, @Nonnull String notify) { this.api = api; this.content = content; this.web = web; @@ -53,7 +54,7 @@ public DbxHost(String api, String content, String web, String notify) { * * @return host name of main Dropbox API server */ - public String getApi() { + public @Nonnull String getApi() { return api; } @@ -63,7 +64,7 @@ public String getApi() { * * @return host name of Dropbox API content server */ - public String getContent() { + public @Nonnull String getContent() { return content; } @@ -73,7 +74,7 @@ public String getContent() { * * @return host name of Dropbox API web server used during user authorization */ - public String getWeb() { + public @Nonnull String getWeb() { return web; } @@ -83,7 +84,7 @@ public String getWeb() { * * @return host name of Dropbox notification server used for longpolling */ - public String getNotify() { + public @Nonnull String getNotify() { return notify; } @@ -93,7 +94,7 @@ public int hashCode() { } @Override - public boolean equals(/*@Nullable*/Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == this) { return true; } else if(obj instanceof DbxHost) { @@ -107,13 +108,13 @@ public boolean equals(/*@Nullable*/Object obj) { } } - private static DbxHost fromBaseHost(String s) { + private static @Nonnull DbxHost fromBaseHost(@Nonnull String s) { return new DbxHost("api-" + s, "api-content-" + s, "meta-" + s, "api-notify-" + s); } - public static final JsonReader Reader = new JsonReader() { + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public DbxHost read(JsonParser parser) throws IOException, JsonReadException { + public @Nonnull DbxHost read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonToken t = parser.getCurrentToken(); if (t == JsonToken.VALUE_STRING) { String s = parser.getText(); @@ -168,7 +169,7 @@ else if (fieldName.equals("notify")) { } }; - private /*@Nullable*/String inferBaseHost() { + private @Nullable String inferBaseHost() { if (web.startsWith("meta-") && api.startsWith("api-") && content.startsWith("api-content-") && notify.startsWith("api-notify-")) { String webBase = web.substring("meta-".length()); String apiBase = api.substring("api-".length()); @@ -181,9 +182,9 @@ else if (fieldName.equals("notify")) { return null; } - public static final JsonWriter Writer = new JsonWriter() { + public static final @Nonnull JsonWriter Writer = new JsonWriter() { @Override - public void write(DbxHost host, JsonGenerator g) throws IOException { + public void write(@Nonnull DbxHost host, @Nonnull JsonGenerator g) throws IOException { String base = host.inferBaseHost(); if (base != null) { g.writeString(base); diff --git a/core/src/main/java/com/dropbox/core/DbxOAuth1AccessToken.java b/core/src/main/java/com/dropbox/core/DbxOAuth1AccessToken.java index ee1ad2625..bf231eaef 100644 --- a/core/src/main/java/com/dropbox/core/DbxOAuth1AccessToken.java +++ b/core/src/main/java/com/dropbox/core/DbxOAuth1AccessToken.java @@ -1,19 +1,21 @@ package com.dropbox.core; +import javax.annotation.Nonnull; + /** * Use with {@link DbxOAuth1Upgrader} to convert old OAuth 1 access tokens * to OAuth 2 access tokens. This SDK doesn't support using OAuth 1 access * tokens for regular API calls. */ public final class DbxOAuth1AccessToken { - private final String key; - private final String secret; + private final @Nonnull String key; + private final @Nonnull String secret; /** * @param key OAuth 1 access token key * @param secret OAuth 2 access token secret */ - public DbxOAuth1AccessToken(String key, String secret) { + public DbxOAuth1AccessToken(@Nonnull String key, @Nonnull String secret) { this.key = key; this.secret = secret; } @@ -23,7 +25,7 @@ public DbxOAuth1AccessToken(String key, String secret) { * * @return OAuth 1 access token key */ - public String getKey() { + public @Nonnull String getKey() { return key; } @@ -32,7 +34,7 @@ public String getKey() { * * @return OAuth 1 access token secret */ - public String getSecret() { + public @Nonnull String getSecret() { return secret; } } diff --git a/core/src/main/java/com/dropbox/core/DbxOAuth1Upgrader.java b/core/src/main/java/com/dropbox/core/DbxOAuth1Upgrader.java index e772892e0..97c5d32ea 100644 --- a/core/src/main/java/com/dropbox/core/DbxOAuth1Upgrader.java +++ b/core/src/main/java/com/dropbox/core/DbxOAuth1Upgrader.java @@ -15,6 +15,8 @@ import java.net.URLEncoder; import java.util.ArrayList; +import javax.annotation.Nonnull; + /** * Lets you convert OAuth 1 access tokens to OAuth 2 access tokens. First call {@link * #createOAuth2AccessToken} to get an OAuth 2 access token. If that succeeds, call {@link @@ -22,14 +24,14 @@ */ public final class DbxOAuth1Upgrader { - private final DbxRequestConfig requestConfig; - private final DbxAppInfo appInfo; + private final @Nonnull DbxRequestConfig requestConfig; + private final @Nonnull DbxAppInfo appInfo; /** * @param appInfo * Your application's Dropbox API information (the app key and secret). */ - public DbxOAuth1Upgrader(DbxRequestConfig requestConfig, DbxAppInfo appInfo) + public DbxOAuth1Upgrader(@Nonnull DbxRequestConfig requestConfig, @Nonnull DbxAppInfo appInfo) { if (requestConfig == null) throw new IllegalArgumentException("'requestConfig' is null"); if (appInfo == null) throw new IllegalArgumentException("'appInfo' is null"); @@ -42,7 +44,7 @@ public DbxOAuth1Upgrader(DbxRequestConfig requestConfig, DbxAppInfo appInfo) * Given an existing active OAuth 1 access token, make a Dropbox API call to get a new OAuth 2 * access token that represents the same user and app. */ - public String createOAuth2AccessToken(DbxOAuth1AccessToken token) + public @Nonnull String createOAuth2AccessToken(@Nonnull DbxOAuth1AccessToken token) throws DbxException { if (token == null) throw new IllegalArgumentException("'token' can't be null"); @@ -55,7 +57,7 @@ public String createOAuth2AccessToken(DbxOAuth1AccessToken token) getHeaders(token), new DbxRequestUtil.ResponseHandler() { @Override - public String handle(HttpRequestor.Response response) throws DbxException { + public @Nonnull String handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); return DbxRequestUtil.readJsonFromResponse(ResponseReader, response); } @@ -66,7 +68,7 @@ public String handle(HttpRequestor.Response response) throws DbxException { /** * Tell the Dropbox API server to disable an OAuth 1 access token. */ - public void disableOAuth1AccessToken(DbxOAuth1AccessToken token) + public void disableOAuth1AccessToken(@Nonnull DbxOAuth1AccessToken token) throws DbxException { if (token == null) throw new IllegalArgumentException("'token' can't be null"); @@ -79,7 +81,7 @@ public void disableOAuth1AccessToken(DbxOAuth1AccessToken token) getHeaders(token), new DbxRequestUtil.ResponseHandler() { @Override - public Void handle(HttpRequestor.Response response) throws DbxException { + public Void handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); return null; } @@ -87,24 +89,29 @@ public Void handle(HttpRequestor.Response response) throws DbxException { ); } - private ArrayList getHeaders(DbxOAuth1AccessToken token) + private @Nonnull ArrayList getHeaders(@Nonnull DbxOAuth1AccessToken token) { ArrayList headers = new ArrayList(1); headers.add(new HttpRequestor.Header("Authorization", buildOAuth1Header(token))); return headers; } - private String buildOAuth1Header(DbxOAuth1AccessToken token) + private @Nonnull String buildOAuth1Header(@Nonnull DbxOAuth1AccessToken token) { + String appSecret = this.appInfo.getSecret(); + if (appSecret == null) { + throw new IllegalStateException("OAuth 1 token upgrade requires an app secret."); + } + StringBuilder buf = new StringBuilder(); buf.append("OAuth oauth_version=\"1.0\", oauth_signature_method=\"PLAINTEXT\""); buf.append(", oauth_consumer_key=\"").append(encode(this.appInfo.getKey())).append("\""); buf.append(", oauth_token=\"").append(encode(token.getKey())).append("\""); - buf.append(", oauth_signature=\"").append(encode(this.appInfo.getSecret())).append("&").append(encode(token.getSecret())).append("\""); + buf.append(", oauth_signature=\"").append(encode(appSecret)).append("&").append(encode(token.getSecret())).append("\""); return buf.toString(); } - private static String encode(String s) + private static @Nonnull String encode(@Nonnull String s) { try { return URLEncoder.encode(s, "UTF-8"); @@ -117,9 +124,9 @@ private static String encode(String s) /** * For JSON parsing. */ - public static final JsonReader ResponseReader = new JsonReader() + public static final @Nonnull JsonReader ResponseReader = new JsonReader() { - public String read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull String read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); diff --git a/core/src/main/java/com/dropbox/core/DbxPKCEManager.java b/core/src/main/java/com/dropbox/core/DbxPKCEManager.java index bd9cbcd32..7cdf9c1a1 100644 --- a/core/src/main/java/com/dropbox/core/DbxPKCEManager.java +++ b/core/src/main/java/com/dropbox/core/DbxPKCEManager.java @@ -13,6 +13,9 @@ import java.util.HashMap; import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import static com.dropbox.core.util.StringUtil.urlSafeBase64Encode; /** @@ -23,15 +26,15 @@ * @see https://tools.ietf.org/html/rfc7636 */ public class DbxPKCEManager { - public static final String CODE_CHALLENGE_METHODS = "S256"; + public static final @Nonnull String CODE_CHALLENGE_METHODS = "S256"; public static final int CODE_VERIFIER_SIZE = 128; private static final SecureRandom RAND = new SecureRandom(); - private static final String CODE_VERIFIER_CHAR_SET = + private static final @Nonnull String CODE_VERIFIER_CHAR_SET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"; - private String codeVerifier; - private String codeChallenge; + private @Nonnull String codeVerifier; + private @Nonnull String codeChallenge; /** * This class has state. Each instance has a randomly generated codeVerifier in it. Just @@ -43,11 +46,12 @@ public DbxPKCEManager() { this.codeChallenge = generateCodeChallenge(this.codeVerifier); } - public DbxPKCEManager(String codeVerifier) { + public DbxPKCEManager(@Nonnull String codeVerifier) { this.codeVerifier = codeVerifier; this.codeChallenge = generateCodeChallenge(this.codeVerifier); } + @Nonnull String generateCodeVerifier() { StringBuilder sb = new StringBuilder(); @@ -58,7 +62,7 @@ String generateCodeVerifier() { return sb.toString(); } - static String generateCodeChallenge(String codeVerifier) { + static @Nonnull String generateCodeChallenge(@Nonnull String codeVerifier) { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] signiture = digest.digest(codeVerifier.getBytes("US-ASCII")); @@ -73,14 +77,14 @@ static String generateCodeChallenge(String codeVerifier) { /** * @return The randomly generate code verifier in this instance. */ - public String getCodeVerifier() { + public @Nonnull String getCodeVerifier() { return this.codeVerifier; } /** * @return The code challenge, which is a hashed code verifier. */ - public String getCodeChallenge() { + public @Nonnull String getCodeChallenge() { return this.codeChallenge; } @@ -96,11 +100,11 @@ public String getCodeChallenge() { * refresh token. * @throws DbxException If reqeust is invalid, or code expired, or server error. */ - public DbxAuthFinish makeTokenRequest(DbxRequestConfig requestConfig, - String oauth2Code, - String appKey, - String redirectUri, - DbxHost host) throws DbxException { + public @Nonnull DbxAuthFinish makeTokenRequest(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String oauth2Code, + @Nonnull String appKey, + @Nullable String redirectUri, + @Nonnull DbxHost host) throws DbxException { Map params = new HashMap(); params.put("grant_type", "authorization_code"); params.put("code", oauth2Code); @@ -121,7 +125,7 @@ public DbxAuthFinish makeTokenRequest(DbxRequestConfig requestConfig, null, new DbxRequestUtil.ResponseHandler() { @Override - public DbxAuthFinish handle(HttpRequestor.Response response) throws DbxException { + public @Nonnull DbxAuthFinish handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) { throw DbxRequestUtil.unexpectedStatus(response); } diff --git a/core/src/main/java/com/dropbox/core/DbxPKCEWebAuth.java b/core/src/main/java/com/dropbox/core/DbxPKCEWebAuth.java index 1e13029ac..6c42f6d55 100644 --- a/core/src/main/java/com/dropbox/core/DbxPKCEWebAuth.java +++ b/core/src/main/java/com/dropbox/core/DbxPKCEWebAuth.java @@ -11,6 +11,9 @@ import java.util.HashMap; import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import static com.dropbox.core.util.StringUtil.urlSafeBase64Encode; /** @@ -38,10 +41,10 @@ * new dropbox oauth guide */ public class DbxPKCEWebAuth { - private final DbxRequestConfig requestConfig; - private final DbxAppInfo appInfo; - private final DbxWebAuth dbxWebAuth; - private final DbxPKCEManager dbxPKCEManager; + private final @Nonnull DbxRequestConfig requestConfig; + private final @Nonnull DbxAppInfo appInfo; + private final @Nonnull DbxWebAuth dbxWebAuth; + private final @Nonnull DbxPKCEManager dbxPKCEManager; private boolean started; private boolean consumed; @@ -54,7 +57,7 @@ public class DbxPKCEWebAuth { * * @throws IllegalStateException if appInfo contains app secret. */ - public DbxPKCEWebAuth(DbxRequestConfig requestConfig, DbxAppInfo appInfo) { + public DbxPKCEWebAuth(@Nonnull DbxRequestConfig requestConfig, @Nonnull DbxAppInfo appInfo) { if (appInfo.hasSecret()) { throw new IllegalStateException("PKCE cdoe flow doesn't require app secret, if you " + "decide to embed it in your app, please use regular DbxWebAuth instead."); @@ -88,7 +91,7 @@ public DbxPKCEWebAuth(DbxRequestConfig requestConfig, DbxAppInfo appInfo) { * @return Authorization URL of website user can use to authorize your app. * */ - public String authorize(DbxWebAuth.Request request) { + public @Nonnull String authorize(@Nonnull DbxWebAuth.Request request) { if (consumed) { throw new IllegalStateException("This DbxPKCEWebAuth instance has been consumed " + "already. To start a new PKCE OAuth flow, please create a new instance."); @@ -112,7 +115,7 @@ public String authorize(DbxWebAuth.Request request) { * URL, or if an error occurs communicating with Dropbox. * @see DbxWebAuth#finishFromCode(String) */ - public DbxAuthFinish finishFromCode(String code) throws DbxException { + public @Nonnull DbxAuthFinish finishFromCode(@Nonnull String code) throws DbxException { return finish(code, null, null); } @@ -134,18 +137,22 @@ public DbxAuthFinish finishFromCode(String code) throws DbxException { * @throws DbxException if the instance is not the same one used to generate authorization * URL, or if an error occurs communicating with Dropbox. */ - public DbxAuthFinish finishFromRedirect(String redirectUri, - DbxSessionStore sessionStore, - Map params) + public @Nonnull DbxAuthFinish finishFromRedirect(@Nonnull String redirectUri, + @Nonnull DbxSessionStore sessionStore, + @Nonnull Map params) throws DbxException, DbxWebAuth.BadRequestException, DbxWebAuth.BadStateException, DbxWebAuth.CsrfException, DbxWebAuth.NotApprovedException, DbxWebAuth.ProviderException { - String strippedState = DbxWebAuth.validateRedirectUri(redirectUri, sessionStore, params); + @Nullable String strippedState = DbxWebAuth.validateRedirectUri(redirectUri, sessionStore, params); String code = DbxWebAuth.getParam(params, "code"); + if (code == null) { + throw new DbxWebAuth.BadRequestException("Missing required parameter: \"code\"."); + } return finish(code, redirectUri, strippedState); } - DbxAuthFinish finish(String code, String redirectUri, final String state) throws DbxException { + @Nonnull + DbxAuthFinish finish(@Nonnull String code, @Nullable String redirectUri, final @Nullable String state) throws DbxException { if (code == null) throw new NullPointerException("code"); if (!this.started) { throw new IllegalStateException("Must initialize the PKCE flow by calling authorize " + diff --git a/core/src/main/java/com/dropbox/core/DbxRequestConfig.java b/core/src/main/java/com/dropbox/core/DbxRequestConfig.java index 54eec5c3e..4da3a5478 100644 --- a/core/src/main/java/com/dropbox/core/DbxRequestConfig.java +++ b/core/src/main/java/com/dropbox/core/DbxRequestConfig.java @@ -1,23 +1,27 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Locale; import com.dropbox.core.http.HttpRequestor; import com.dropbox.core.http.StandardHttpRequestor; -/*>>> import checkers.nullness.quals.Nullable; */ /** * A grouping of a few configuration parameters for how we should make requests to the * Dropbox servers. */ public class DbxRequestConfig { - private final String clientIdentifier; - private final /*@Nullable*/String userLocale; - private final HttpRequestor httpRequestor; + private final @Nonnull String clientIdentifier; + private final @Nullable String userLocale; + private final @Nonnull HttpRequestor httpRequestor; private final int maxRetries; - private DbxRequestConfig(String clientIdentifier, /*@Nullable*/ String userLocale, HttpRequestor httpRequestor, int maxRetries) { + private DbxRequestConfig(@Nonnull String clientIdentifier, + @Nullable String userLocale, + @Nonnull HttpRequestor httpRequestor, + int maxRetries) { if (clientIdentifier == null) throw new NullPointerException("clientIdentifier"); if (httpRequestor == null) throw new NullPointerException("httpRequestor"); if (maxRetries < 0) throw new IllegalArgumentException("maxRetries"); @@ -33,7 +37,7 @@ private DbxRequestConfig(String clientIdentifier, /*@Nullable*/ String userLocal * * @param clientIdentifier see {@link #getClientIdentifier} */ - public DbxRequestConfig(String clientIdentifier) { + public DbxRequestConfig(@Nonnull String clientIdentifier) { this(clientIdentifier, null); } @@ -46,7 +50,7 @@ public DbxRequestConfig(String clientIdentifier) { * @deprecated Use {@link #newBuilder} to customize configuration */ @Deprecated - public DbxRequestConfig(String clientIdentifier, /*@Nullable*/ String userLocale) { + public DbxRequestConfig(@Nonnull String clientIdentifier, @Nullable String userLocale) { this(clientIdentifier, userLocale, StandardHttpRequestor.INSTANCE); } @@ -60,7 +64,9 @@ public DbxRequestConfig(String clientIdentifier, /*@Nullable*/ String userLocale * @deprecated Use {@link #newBuilder} to customize configuration */ @Deprecated - public DbxRequestConfig(String clientIdentifier, /*@Nullable*/ String userLocale, HttpRequestor httpRequestor) { + public DbxRequestConfig(@Nonnull String clientIdentifier, + @Nullable String userLocale, + @Nonnull HttpRequestor httpRequestor) { this(clientIdentifier, userLocale, httpRequestor, 0); } @@ -82,7 +88,7 @@ public DbxRequestConfig(String clientIdentifier, /*@Nullable*/ String userLocale * debugging things later. *

*/ - public String getClientIdentifier() { + public @Nonnull String getClientIdentifier() { return clientIdentifier; } @@ -106,7 +112,7 @@ public String getClientIdentifier() { * to the user's configured locale setting. *

*/ - public String getUserLocale() { + public @Nullable String getUserLocale() { return userLocale; } @@ -114,7 +120,7 @@ public String getUserLocale() { * Returns the {@link HttpRequestor} you passed in when constructing this object, which * defaults to {@link StandardHttpRequestor#INSTANCE}. */ - public HttpRequestor getHttpRequestor() { + public @Nonnull HttpRequestor getHttpRequestor() { return httpRequestor; } @@ -162,7 +168,7 @@ public int getMaxRetries() { * * @return builder configured to build a copy of this instance */ - public Builder copy() { + public @Nonnull Builder copy() { return new Builder(clientIdentifier, userLocale, httpRequestor, maxRetries); } @@ -172,13 +178,13 @@ public Builder copy() { * * @param clientIdentifier see {@link #getClientIdentifier} */ - public static Builder newBuilder(String clientIdentifier) { + public static @Nonnull Builder newBuilder(@Nonnull String clientIdentifier) { if (clientIdentifier == null) throw new NullPointerException("clientIdentifier"); return new Builder(clientIdentifier); } // Available in Java 7, but not in Java 6. Do a hacky version of it here. - private static String toLanguageTag(Locale locale) { + private static @Nullable String toLanguageTag(@Nullable Locale locale) { if (locale == null) { return null; } @@ -197,7 +203,7 @@ private static String toLanguageTag(Locale locale) { // APIv1 accepts Locale.toString() formatted locales (e.g. 'en_US'), but APIv2 will return an // error if the locale is not in proper Language Tag format. Attempt to convert old locale // formats to the new one. - private static String toLanguageTag(String locale) { + private static @Nullable String toLanguageTag(@Nullable String locale) { if (locale == null) { return null; } @@ -226,15 +232,15 @@ private static String toLanguageTag(String locale) { * Builder for {@link DbxRequestConfig}. */ public static final class Builder { - private final String clientIdentifier; + private final @Nonnull String clientIdentifier; - private /*@Nullable*/ String userLocale; - private HttpRequestor httpRequestor; + private @Nullable String userLocale; + private @Nonnull HttpRequestor httpRequestor; private int maxRetries; - private Builder(String clientIdentifier, - /*@Nullable*/ String userLocale, - HttpRequestor httpRequestor, + private Builder(@Nonnull String clientIdentifier, + @Nullable String userLocale, + @Nonnull HttpRequestor httpRequestor, int maxRetries) { this.clientIdentifier = clientIdentifier; this.userLocale = userLocale; @@ -242,7 +248,7 @@ private Builder(String clientIdentifier, this.maxRetries = maxRetries; } - private Builder(String clientIdentifier) { + private Builder(@Nonnull String clientIdentifier) { this.clientIdentifier = clientIdentifier; this.userLocale = null; @@ -262,7 +268,7 @@ private Builder(String clientIdentifier) { * * @return this builder */ - public Builder withUserLocale(/*@Nullable*/ String userLocale) { + public @Nonnull Builder withUserLocale(@Nullable String userLocale) { this.userLocale = userLocale; return this; } @@ -276,7 +282,7 @@ public Builder withUserLocale(/*@Nullable*/ String userLocale) { * * @return this builder */ - public Builder withUserLocaleFromPreferences() { + public @Nonnull Builder withUserLocaleFromPreferences() { this.userLocale = null; return this; } @@ -292,7 +298,7 @@ public Builder withUserLocaleFromPreferences() { * * @return this builder */ - public Builder withUserLocaleFrom(/*@Nullable*/ Locale userLocale) { // not named withUserLocale because of ambiguous calls when passing 'null' + public @Nonnull Builder withUserLocaleFrom(@Nullable Locale userLocale) { // not named withUserLocale because of ambiguous calls when passing 'null' this.userLocale = toLanguageTag(userLocale); return this; } @@ -306,7 +312,7 @@ public Builder withUserLocaleFrom(/*@Nullable*/ Locale userLocale) { // not name * * @return this builder */ - public Builder withHttpRequestor(HttpRequestor httpRequestor) { + public @Nonnull Builder withHttpRequestor(@Nonnull HttpRequestor httpRequestor) { if (httpRequestor == null) throw new NullPointerException("httpRequestor"); this.httpRequestor = httpRequestor; return this; @@ -324,7 +330,7 @@ public Builder withHttpRequestor(HttpRequestor httpRequestor) { * * @return this builder */ - public Builder withAutoRetryEnabled() { + public @Nonnull Builder withAutoRetryEnabled() { return withAutoRetryEnabled(3); } @@ -338,7 +344,7 @@ public Builder withAutoRetryEnabled() { * * @see #withAutoRetryEnabled */ - public Builder withAutoRetryDisabled() { + public @Nonnull Builder withAutoRetryDisabled() { this.maxRetries = 0; return this; } @@ -365,7 +371,7 @@ public Builder withAutoRetryDisabled() { * * @throws IllegalArgumentException if {@code maxRetries} is not positive. */ - public Builder withAutoRetryEnabled(int maxRetries) { + public @Nonnull Builder withAutoRetryEnabled(int maxRetries) { if (maxRetries <= 0) throw new IllegalArgumentException("maxRetries must be positive"); this.maxRetries = maxRetries; return this; @@ -377,7 +383,7 @@ public Builder withAutoRetryEnabled(int maxRetries) { * * @return new {@code DbxRequestConfig} instance. */ - public DbxRequestConfig build() { + public @Nonnull DbxRequestConfig build() { return new DbxRequestConfig(clientIdentifier, userLocale, httpRequestor, maxRetries); } } diff --git a/core/src/main/java/com/dropbox/core/DbxRequestUtil.java b/core/src/main/java/com/dropbox/core/DbxRequestUtil.java index 3f3df6d81..725dddf5c 100644 --- a/core/src/main/java/com/dropbox/core/DbxRequestUtil.java +++ b/core/src/main/java/com/dropbox/core/DbxRequestUtil.java @@ -1,5 +1,7 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; @@ -32,14 +34,13 @@ import static com.dropbox.core.util.StringUtil.jq; import static com.dropbox.core.util.LangUtil.mkAssert; -/*>>> import checkers.nullness.quals.Nullable; */ public final class DbxRequestUtil { private static final Random RAND = new Random(); - public static DbxGlobalCallbackFactory sharedCallbackFactory; + public static @Nullable DbxGlobalCallbackFactory sharedCallbackFactory; - public static String encodeUrlParam(String s) { + public static @Nonnull String encodeUrlParam(@Nonnull String s) { try { return URLEncoder.encode(s, "UTF-8"); } catch (UnsupportedEncodingException ex) { @@ -47,14 +48,14 @@ public static String encodeUrlParam(String s) { } } - public static String buildUrlWithParams(/*@Nullable*/String userLocale, - String host, - String path, - /*@Nullable*/String/*@Nullable*/[] params) { + public static @Nonnull String buildUrlWithParams(@Nullable String userLocale, + @Nonnull String host, + @Nonnull String path, + @Nullable String[] params) { return buildUri(host, path) + "?" + encodeUrlParams(userLocale, params); } - public static String [] toParamsArray(Map params) { + public static @Nonnull String [] toParamsArray(@Nonnull Map params) { String [] arr = new String[2 * params.size()]; int i = 0; for (Map.Entry entry : params.entrySet()) { @@ -65,7 +66,7 @@ public static String buildUrlWithParams(/*@Nullable*/String userLocale, return arr; } - public static String buildUri(String host, String path) { + public static @Nonnull String buildUri(@Nonnull String host, @Nonnull String path) { try { return new URI("https", host, "/" + path, null).toASCIIString(); } @@ -74,8 +75,8 @@ public static String buildUri(String host, String path) { } } - private static String encodeUrlParams(/*@Nullable*/String userLocale, - /*@Nullable*/String/*@Nullable*/[] params) { + private static @Nonnull String encodeUrlParams(@Nullable String userLocale, + @Nullable String[] params) { StringBuilder buf = new StringBuilder(); String sep = ""; if (userLocale != null) { @@ -104,7 +105,8 @@ private static String encodeUrlParams(/*@Nullable*/String userLocale, return buf.toString(); } - public static List addAuthHeader(/*@Nullable*/List headers, String accessToken) { + public static @Nonnull List addAuthHeader(@Nullable List headers, + @Nonnull String accessToken) { if (accessToken == null) throw new NullPointerException("accessToken"); if (headers == null) headers = new ArrayList(); @@ -112,7 +114,8 @@ public static List addAuthHeader(/*@Nullable*/List addSelectUserHeader(/*@Nullable*/List headers, String memberId) { + public static @Nonnull List addSelectUserHeader(@Nullable List headers, + @Nonnull String memberId) { if (memberId == null) throw new NullPointerException("memberId"); if (headers == null) headers = new ArrayList(); @@ -120,7 +123,8 @@ public static List addSelectUserHeader(/*@Nullable*/List addSelectAdminHeader(/*@Nullable*/List headers, String adminId) { + public static @Nonnull List addSelectAdminHeader(@Nullable List headers, + @Nonnull String adminId) { if (adminId == null) throw new NullPointerException("adminId"); if (headers == null) headers = new ArrayList(); @@ -128,7 +132,9 @@ public static List addSelectAdminHeader(/*@Nullable*/List< return headers; } - public static List addBasicAuthHeader(/*@Nullable*/List headers, String username, String password) { + public static @Nonnull List addBasicAuthHeader(@Nullable List headers, + @Nonnull String username, + @Nonnull String password) { if (username == null) throw new NullPointerException("username"); if (password == null) throw new NullPointerException("password"); if (headers == null) headers = new ArrayList(); @@ -139,17 +145,18 @@ public static List addBasicAuthHeader(/*@Nullable*/List addUserAgentHeader( - /*@Nullable*/List headers, - DbxRequestConfig requestConfig, - String sdkUserAgentIdentifier + public static @Nonnull List addUserAgentHeader( + @Nullable List headers, + @Nonnull DbxRequestConfig requestConfig, + @Nonnull String sdkUserAgentIdentifier ) { if (headers == null) headers = new ArrayList(); headers.add(buildUserAgentHeader(requestConfig, sdkUserAgentIdentifier)); return headers; } - public static List addUserLocaleHeader(/*@Nullable*/List headers, DbxRequestConfig requestConfig) { + public static @Nullable List addUserLocaleHeader(@Nullable List headers, + @Nonnull DbxRequestConfig requestConfig) { if (requestConfig.getUserLocale() == null) { return headers; } @@ -159,11 +166,13 @@ public static List addUserLocaleHeader(/*@Nullable*/List addPathRootHeader(/*@Nullable*/List headers, PathRoot pathRoot) { + public static @Nullable List addPathRootHeader(@Nullable List headers, + @Nullable PathRoot pathRoot) { if (pathRoot == null) { return headers; } @@ -173,7 +182,7 @@ public static List addPathRootHeader(/*@Nullable*/List removeAuthHeader(/*@Nullable*/List headers) { + public static @Nonnull List removeAuthHeader(@Nullable List headers) { if (headers == null) { return new ArrayList(); } @@ -193,13 +202,13 @@ public static List removeAuthHeader(/*@Nullable*/List headers) + public static @Nonnull HttpRequestor.Response startGet(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String accessToken, + @Nonnull String sdkUserAgentIdentifier, + @Nonnull String host, + @Nonnull String path, + @Nullable String[] params, + @Nullable List headers) throws NetworkIOException { headers = copyHeaders(headers); headers = addUserAgentHeader(headers, requestConfig, sdkUserAgentIdentifier); @@ -217,12 +226,12 @@ public static HttpRequestor.Response startGet(DbxRequestConfig requestConfig, /** * Convenience function for making HTTP PUT requests. */ - public static HttpRequestor.Uploader startPut(DbxRequestConfig requestConfig, - String accessToken, - String sdkUserAgentIdentifier, - String host, String path, - /*@Nullable*/String/*@Nullable*/[] params, - /*@Nullable*/List headers) + public static @Nonnull HttpRequestor.Uploader startPut(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String accessToken, + @Nonnull String sdkUserAgentIdentifier, + @Nonnull String host, @Nonnull String path, + @Nullable String[] params, + @Nullable List headers) throws NetworkIOException { headers = copyHeaders(headers); headers = addUserAgentHeader(headers, requestConfig, sdkUserAgentIdentifier); @@ -240,12 +249,12 @@ public static HttpRequestor.Uploader startPut(DbxRequestConfig requestConfig, /** * Convenience function for making HTTP POST requests. */ - public static HttpRequestor.Response startPostNoAuth(DbxRequestConfig requestConfig, - String sdkUserAgentIdentifier, - String host, - String path, - /*@Nullable*/String/*@Nullable*/[] params, - /*@Nullable*/List headers) + public static @Nonnull HttpRequestor.Response startPostNoAuth(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String sdkUserAgentIdentifier, + @Nonnull String host, + @Nonnull String path, + @Nullable String[] params, + @Nullable List headers) throws NetworkIOException { byte[] encodedParams = StringUtil.stringToUtf8(encodeUrlParams(requestConfig.getUserLocale(), params)); @@ -259,12 +268,12 @@ public static HttpRequestor.Response startPostNoAuth(DbxRequestConfig requestCon /** * Convenience function for making HTTP POST requests. Like startPostNoAuth but takes byte[] instead of params. */ - public static HttpRequestor.Response startPostRaw(DbxRequestConfig requestConfig, - String sdkUserAgentIdentifier, - String host, - String path, - byte[] body, - /*@Nullable*/List headers) + public static @Nonnull HttpRequestor.Response startPostRaw(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String sdkUserAgentIdentifier, + @Nonnull String host, + @Nonnull String path, + @Nonnull byte[] body, + @Nullable List headers) throws NetworkIOException { String uri = buildUri(host, path); @@ -285,7 +294,7 @@ public static HttpRequestor.Response startPostRaw(DbxRequestConfig requestConfig } } - private static List copyHeaders(List headers) { + private static @Nonnull List copyHeaders(@Nullable List headers) { if (headers == null) { return new ArrayList(); } else { @@ -293,7 +302,7 @@ private static List copyHeaders(List } } - public static byte[] loadErrorBody(HttpRequestor.Response response) + public static @Nonnull byte[] loadErrorBody(@Nonnull HttpRequestor.Response response) throws NetworkIOException { if (response.getBody() == null) { return new byte[0]; @@ -308,7 +317,7 @@ public static byte[] loadErrorBody(HttpRequestor.Response response) } - public static String parseErrorBody(String requestId, int statusCode, byte[] body) + public static @Nonnull String parseErrorBody(@Nullable String requestId, int statusCode, @Nonnull byte[] body) throws BadResponseException { // Read the error message from the body. // TODO: Get charset from the HTTP Content-Type header. It's wrong to just assume UTF-8. @@ -320,11 +329,11 @@ public static String parseErrorBody(String requestId, int statusCode, byte[] bod } } - public static DbxException unexpectedStatus(HttpRequestor.Response response) throws NetworkIOException, BadResponseException { + public static @Nonnull DbxException unexpectedStatus(@Nonnull HttpRequestor.Response response) throws NetworkIOException, BadResponseException { return DbxRequestUtil.unexpectedStatus(response, null); } - public static DbxException unexpectedStatus(HttpRequestor.Response response, String userId) + public static @Nonnull DbxException unexpectedStatus(@Nonnull HttpRequestor.Response response, @Nullable String userId) throws NetworkIOException, BadResponseException { String requestId = getRequestId(response); @@ -426,13 +435,15 @@ public static DbxException unexpectedStatus(HttpRequestor.Response response, Str return networkError; } - private static String messageFromResponse(HttpRequestor.Response response, String requestId) throws NetworkIOException, BadResponseException { + private static @Nonnull String messageFromResponse(@Nonnull HttpRequestor.Response response, + @Nullable String requestId) throws NetworkIOException, BadResponseException { byte[] body = loadErrorBody(response); String message = parseErrorBody(requestId, response.getStatusCode(), body); return message; } - public static T readJsonFromResponse(JsonReader reader, HttpRequestor.Response response) + public static @Nullable T readJsonFromResponse(@Nonnull JsonReader reader, + @Nonnull HttpRequestor.Response response) throws BadResponseException, NetworkIOException { try { return reader.readFully(response.getBody()); @@ -444,75 +455,73 @@ public static T readJsonFromResponse(JsonReader reader, HttpRequestor.Res } } - public static T readJsonFromErrorMessage(StoneSerializer serializer, String message, String requestId) + public static @Nonnull T readJsonFromErrorMessage(@Nonnull StoneSerializer serializer, + @Nonnull String message, + @Nullable String requestId) throws JsonParseException { ApiErrorResponse errorResponse = new ApiErrorResponse.Serializer(serializer).deserialize(message); return errorResponse.getError(); } public static abstract class ResponseHandler { - public abstract T handle(HttpRequestor.Response response) throws DbxException; + public abstract @Nullable T handle(@Nonnull HttpRequestor.Response response) throws DbxException; } - public static T doGet(final DbxRequestConfig requestConfig, - final String accessToken, - final String sdkUserAgentIdentifier, - final String host, - final String path, - final /*@Nullable*/String/*@Nullable*/[] params, - final /*@Nullable*/List headers, - final ResponseHandler handler) + public static @Nullable T doGet(final @Nonnull DbxRequestConfig requestConfig, + final @Nonnull String accessToken, + final @Nonnull String sdkUserAgentIdentifier, + final @Nonnull String host, + final @Nonnull String path, + final @Nullable String[] params, + final @Nullable List headers, + final @Nonnull ResponseHandler handler) throws DbxException { return runAndRetry(requestConfig.getMaxRetries(), new RequestMaker() { @Override - public T run() throws DbxException { + public @Nullable T run() throws DbxException { HttpRequestor.Response response = startGet(requestConfig, accessToken, sdkUserAgentIdentifier, host, path, params, headers); try { return handler.handle(response); } finally { - try { - response.getBody().close(); - } catch (IOException ex) { - //noinspection ThrowFromFinallyBlock - throw new NetworkIOException(ex); - } + IOUtil.closeInput(response.getBody()); } } }); } - public static T doPost(DbxRequestConfig requestConfig, - String accessToken, - String sdkUserAgentIdentifier, - String host, - String path, - /*@Nullable*/String/*@Nullable*/[] params, - /*@Nullable*/List headers, - ResponseHandler handler) + public static @Nullable T doPost(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String accessToken, + @Nonnull String sdkUserAgentIdentifier, + @Nonnull String host, + @Nonnull String path, + @Nullable String[] params, + @Nullable List headers, + @Nonnull ResponseHandler handler) throws DbxException { headers = copyHeaders(headers); headers = addAuthHeader(headers, accessToken); return doPostNoAuth(requestConfig, sdkUserAgentIdentifier, host, path, params, headers, handler); } - public static T doPostNoAuth(final DbxRequestConfig requestConfig, - final String sdkUserAgentIdentifier, - final String host, - final String path, - final /*@Nullable*/String/*@Nullable*/[] params, - final /*@Nullable*/List headers, - final ResponseHandler handler) + public static @Nullable T doPostNoAuth(final @Nonnull DbxRequestConfig requestConfig, + final @Nonnull String sdkUserAgentIdentifier, + final @Nonnull String host, + final @Nonnull String path, + final @Nullable String[] params, + final @Nullable List headers, + final @Nonnull ResponseHandler handler) throws DbxException { return runAndRetry(requestConfig.getMaxRetries(), new RequestMaker() { @Override - public T run() throws DbxException { + public @Nullable T run() throws DbxException { HttpRequestor.Response response = startPostNoAuth(requestConfig, sdkUserAgentIdentifier, host, path, params, headers); return finishResponse(response, handler); } }); } - public static T finishResponse(HttpRequestor.Response response, ResponseHandler handler) throws DbxException { + public static @Nullable T finishResponse(@Nonnull HttpRequestor.Response response, + @Nonnull ResponseHandler handler) throws DbxException { try { return handler.handle(response); } finally { @@ -522,7 +531,8 @@ public static T finishResponse(HttpRequestor.Response response, ResponseHand } } - public static String getFirstHeader(HttpRequestor.Response response, String name) throws BadResponseException { + public static @Nonnull String getFirstHeader(@Nonnull HttpRequestor.Response response, + @Nonnull String name) throws BadResponseException { List values = response.getHeaders().get(name); if (values == null || values.isEmpty()) { throw new BadResponseException(getRequestId(response), "missing HTTP header \"" + name + "\""); @@ -530,7 +540,7 @@ public static String getFirstHeader(HttpRequestor.Response response, String name return values.get(0); } - public static /*@Nullable*/String getFirstHeaderMaybe(HttpRequestor.Response response, String name) { + public static @Nullable String getFirstHeaderMaybe(@Nonnull HttpRequestor.Response response, @Nonnull String name) { List values = response.getHeaders().get(name); if (values == null || values.isEmpty()) { return null; @@ -538,19 +548,20 @@ public static String getFirstHeader(HttpRequestor.Response response, String name return values.get(0); } - public static /*@Nullable*/ String getRequestId(HttpRequestor.Response response) { + public static @Nullable String getRequestId(@Nonnull HttpRequestor.Response response) { return DbxRequestUtil.getFirstHeaderMaybe(response, "X-Dropbox-Request-Id"); } - public static /*@Nullable*/ String getContentType(HttpRequestor.Response response) { + public static @Nullable String getContentType(@Nonnull HttpRequestor.Response response) { return DbxRequestUtil.getFirstHeaderMaybe(response, "Content-Type"); } public static abstract class RequestMaker { - public abstract T run() throws DbxException, E; + public abstract @Nullable T run() throws DbxException, E; } - public static T runAndRetry(int maxRetries, RequestMaker requestMaker) + public static @Nullable T runAndRetry(int maxRetries, + @Nonnull RequestMaker requestMaker) throws DbxException, E { int numRetries = 0; while (true) { diff --git a/core/src/main/java/com/dropbox/core/DbxSessionStore.java b/core/src/main/java/com/dropbox/core/DbxSessionStore.java index ad2e887ad..45c660465 100644 --- a/core/src/main/java/com/dropbox/core/DbxSessionStore.java +++ b/core/src/main/java/com/dropbox/core/DbxSessionStore.java @@ -1,6 +1,7 @@ package com.dropbox.core; -/*>>> import checkers.nullness.quals.Nullable; */ +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * An interface that lets you save, retrieve, and clear a single value in the user's web @@ -12,7 +13,7 @@ * */ public interface DbxSessionStore { - public /*@Nullable*/String get(); - public void set(String value); + public @Nullable String get(); + public void set(@Nonnull String value); public void clear(); } diff --git a/core/src/main/java/com/dropbox/core/DbxStandardSessionStore.java b/core/src/main/java/com/dropbox/core/DbxStandardSessionStore.java index 8525e95c3..c2210b439 100644 --- a/core/src/main/java/com/dropbox/core/DbxStandardSessionStore.java +++ b/core/src/main/java/com/dropbox/core/DbxStandardSessionStore.java @@ -1,8 +1,9 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import jakarta.servlet.http.HttpSession; -/*>>> import checkers.nullness.quals.Nullable; */ /** * A {@link DbxSessionStore} implementation that stores the value using the standard @@ -20,31 +21,31 @@ * */ public final class DbxStandardSessionStore implements DbxSessionStore { - private final HttpSession session; - private final String key; + private final @Nonnull HttpSession session; + private final @Nonnull String key; - public DbxStandardSessionStore(HttpSession session, String key) { + public DbxStandardSessionStore(@Nonnull HttpSession session, @Nonnull String key) { this.session = session; this.key = key; } - public HttpSession getSession() { + public @Nonnull HttpSession getSession() { return session; } - public String getKey() { + public @Nonnull String getKey() { return key; } @Override - public /*@Nullable*/String get() { + public @Nullable String get() { Object v = session.getAttribute(key); if (v instanceof String) return (String) v; return null; } @Override - public void set(String value) { + public void set(@Nonnull String value) { session.setAttribute(key, value); } diff --git a/core/src/main/java/com/dropbox/core/DbxStreamReader.java b/core/src/main/java/com/dropbox/core/DbxStreamReader.java index 7d7749d35..60c5bcb07 100644 --- a/core/src/main/java/com/dropbox/core/DbxStreamReader.java +++ b/core/src/main/java/com/dropbox/core/DbxStreamReader.java @@ -6,6 +6,8 @@ import java.io.InputStream; import java.io.OutputStream; +import javax.annotation.Nonnull; + /** * A callback for streaming data from an {@link InputStream}. * @@ -21,7 +23,7 @@ public abstract class DbxStreamReader * call {@link InputStream#close close()} on the stream (the stream will * be closed automatically). */ - public abstract void read(NoThrowInputStream in) throws E; + public abstract void read(@Nonnull NoThrowInputStream in) throws E; /** * A {@link DbxStreamReader} that gets its source data from the given {@code OutputStream}. @@ -29,14 +31,14 @@ public abstract class DbxStreamReader */ public static final class OutputStreamCopier extends DbxStreamReader { - private final OutputStream dest; + private final @Nonnull OutputStream dest; - public OutputStreamCopier(OutputStream dest) + public OutputStreamCopier(@Nonnull OutputStream dest) { this.dest = dest; } - public void read(NoThrowInputStream source) throws IOException + public void read(@Nonnull NoThrowInputStream source) throws IOException { IOUtil.copyStreamToStream(source, dest); } @@ -44,11 +46,11 @@ public void read(NoThrowInputStream source) throws IOException public static final class ByteArrayCopier extends DbxStreamReader { - private final byte[] data; + private final @Nonnull byte[] data; private final int offset; private final int length; - public ByteArrayCopier(byte[] data, int offset, int length) + public ByteArrayCopier(@Nonnull byte[] data, int offset, int length) { if (data == null) throw new IllegalArgumentException("'data' can't be null"); if (offset < 0 || offset >= data.length) throw new IllegalArgumentException("'offset' is out of bounds"); @@ -58,13 +60,13 @@ public ByteArrayCopier(byte[] data, int offset, int length) this.length = length; } - public ByteArrayCopier(byte[] data) + public ByteArrayCopier(@Nonnull byte[] data) { this(data, 0, data.length); } @Override - public void read(NoThrowInputStream in) + public void read(@Nonnull NoThrowInputStream in) { in.read(this.data, this.offset, this.length); } diff --git a/core/src/main/java/com/dropbox/core/DbxStreamWriter.java b/core/src/main/java/com/dropbox/core/DbxStreamWriter.java index 10df245e2..9859282ad 100644 --- a/core/src/main/java/com/dropbox/core/DbxStreamWriter.java +++ b/core/src/main/java/com/dropbox/core/DbxStreamWriter.java @@ -6,6 +6,8 @@ import java.io.InputStream; import java.io.OutputStream; +import javax.annotation.Nonnull; + /** * A callback for streaming data to an {@link OutputStream}. * @@ -21,7 +23,7 @@ public abstract class DbxStreamWriter * call {@link OutputStream#close close()} on the stream (the stream will * be closed automatically). */ - public abstract void write(NoThrowOutputStream out) throws E; + public abstract void write(@Nonnull NoThrowOutputStream out) throws E; /** * A {@link DbxStreamWriter} that gets its source data from the given {@code InputStream}. @@ -29,14 +31,14 @@ public abstract class DbxStreamWriter */ public static final class InputStreamCopier extends DbxStreamWriter { - private final InputStream source; + private final @Nonnull InputStream source; - public InputStreamCopier(InputStream source) + public InputStreamCopier(@Nonnull InputStream source) { this.source = source; } - public void write(NoThrowOutputStream out) throws IOException + public void write(@Nonnull NoThrowOutputStream out) throws IOException { IOUtil.copyStreamToStream(source, out); } @@ -44,11 +46,11 @@ public void write(NoThrowOutputStream out) throws IOException public static final class ByteArrayCopier extends DbxStreamWriter { - private final byte[] data; + private final @Nonnull byte[] data; private final int offset; private final int length; - public ByteArrayCopier(byte[] data, int offset, int length) + public ByteArrayCopier(@Nonnull byte[] data, int offset, int length) { if (data == null) throw new IllegalArgumentException("'data' can't be null"); if (offset < 0 || offset >= data.length) throw new IllegalArgumentException("'offset' is out of bounds"); @@ -58,13 +60,13 @@ public ByteArrayCopier(byte[] data, int offset, int length) this.length = length; } - public ByteArrayCopier(byte[] data) + public ByteArrayCopier(@Nonnull byte[] data) { this(data, 0, data.length); } @Override - public void write(NoThrowOutputStream out) + public void write(@Nonnull NoThrowOutputStream out) { out.write(this.data, this.offset, this.length); } diff --git a/core/src/main/java/com/dropbox/core/DbxUploader.java b/core/src/main/java/com/dropbox/core/DbxUploader.java index e2c1d7d61..339a36791 100644 --- a/core/src/main/java/com/dropbox/core/DbxUploader.java +++ b/core/src/main/java/com/dropbox/core/DbxUploader.java @@ -11,6 +11,9 @@ import com.dropbox.core.http.HttpRequestor; import com.dropbox.core.util.IOUtil; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Class for completing upload requests. * @@ -43,16 +46,19 @@ * @param exception type returned by server on request failure */ public abstract class DbxUploader implements Closeable { - private final HttpRequestor.Uploader httpUploader; - private final StoneSerializer responseSerializer; - private final StoneSerializer errorSerializer; + private final @Nonnull HttpRequestor.Uploader httpUploader; + private final @Nonnull StoneSerializer responseSerializer; + private final @Nonnull StoneSerializer errorSerializer; private boolean closed; private boolean finished; - private final String userId; + private final @Nullable String userId; - protected DbxUploader(HttpRequestor.Uploader httpUploader, StoneSerializer responseSerializer, StoneSerializer errorSerializer, String userId) { + protected DbxUploader(@Nonnull HttpRequestor.Uploader httpUploader, + @Nonnull StoneSerializer responseSerializer, + @Nonnull StoneSerializer errorSerializer, + @Nullable String userId) { this.httpUploader = httpUploader; this.responseSerializer = responseSerializer; this.errorSerializer = errorSerializer; @@ -62,7 +68,7 @@ protected DbxUploader(HttpRequestor.Uploader httpUploader, StoneSerializer re this.userId = userId; } - protected abstract X newException(DbxWrappedException error); + protected abstract @Nonnull X newException(@Nonnull DbxWrappedException error); /** * Uploads all bytes read from the given {@link InputStream} and returns the response. @@ -92,7 +98,7 @@ protected DbxUploader(HttpRequestor.Uploader httpUploader, StoneSerializer re * @throws IOException if an error occurs reading the input stream. * @throws IllegalStateException if this uploader has already been closed (see {@link #close}) or finished (see {@link #finish}) */ - public R uploadAndFinish(InputStream in) throws X, DbxException, IOException { + public @Nullable R uploadAndFinish(@Nonnull InputStream in) throws X, DbxException, IOException { return uploadAndFinish(in, null); } @@ -111,7 +117,8 @@ public R uploadAndFinish(InputStream in) throws X, DbxException, IOException { * @throws IOException if an error occurs reading the input stream. * @throws IllegalStateException if this uploader has already been closed (see {@link #close}) or finished (see {@link #finish}) */ - public R uploadAndFinish(InputStream in, IOUtil.ProgressListener progressListener) throws X, DbxException, IOException { + public @Nullable R uploadAndFinish(@Nonnull InputStream in, + @Nullable IOUtil.ProgressListener progressListener) throws X, DbxException, IOException { try { try { httpUploader.setProgressListener(progressListener); @@ -163,7 +170,7 @@ public R uploadAndFinish(InputStream in, IOUtil.ProgressListener progressListene * @throws IOException if an error occurs reading the input stream. * @throws IllegalStateException if this uploader has already been closed (see {@link #close}) or finished (see {@link #finish}) */ - public R uploadAndFinish(InputStream in, long limit) throws X, DbxException, IOException { + public @Nullable R uploadAndFinish(@Nonnull InputStream in, long limit) throws X, DbxException, IOException { return uploadAndFinish(IOUtil.limit(in, limit)); } @@ -183,7 +190,9 @@ public R uploadAndFinish(InputStream in, long limit) throws X, DbxException, IOE * @throws IOException if an error occurs reading the input stream. * @throws IllegalStateException if this uploader has already been closed (see {@link #close}) or finished (see {@link #finish}) */ - public R uploadAndFinish(InputStream in, long limit, IOUtil.ProgressListener progressListener) throws X, DbxException, IOException { + public @Nullable R uploadAndFinish(@Nonnull InputStream in, + long limit, + @Nullable IOUtil.ProgressListener progressListener) throws X, DbxException, IOException { return uploadAndFinish(IOUtil.limit(in, limit), progressListener); } @@ -232,7 +241,7 @@ public void abort() { * * @see #uploadAndFinish(InputStream) */ - public OutputStream getOutputStream() { + public @Nonnull OutputStream getOutputStream() { assertOpenAndUnfinished(); return this.httpUploader.getBody(); } @@ -254,7 +263,7 @@ public OutputStream getOutputStream() { * * @see #uploadAndFinish(InputStream) */ - public OutputStream getOutputStream(IOUtil.ProgressListener progressListener) { + public @Nonnull OutputStream getOutputStream(@Nullable IOUtil.ProgressListener progressListener) { this.httpUploader.setProgressListener(progressListener); return getOutputStream(); } @@ -271,7 +280,7 @@ public OutputStream getOutputStream(IOUtil.ProgressListener progressListener) { * @throws DbxException if an error occurs sending the upload or reading the response * @throws IllegalStateException if this uploader has already been closed (see {@link #close}) or finished (see {@link #finish}) */ - public R finish() throws X, DbxException { + public @Nullable R finish() throws X, DbxException { assertOpenAndUnfinished(); HttpRequestor.Response response = null; diff --git a/core/src/main/java/com/dropbox/core/DbxWebAuth.java b/core/src/main/java/com/dropbox/core/DbxWebAuth.java index 4baef1f07..327f9aaec 100644 --- a/core/src/main/java/com/dropbox/core/DbxWebAuth.java +++ b/core/src/main/java/com/dropbox/core/DbxWebAuth.java @@ -1,5 +1,7 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import static com.dropbox.core.util.StringUtil.jq; import java.nio.charset.Charset; @@ -14,7 +16,6 @@ import com.dropbox.core.util.StringUtil; import com.dropbox.core.v2.DbxRawClientV2; -/*>>> import checkers.nullness.quals.Nullable; */ /** * Does the OAuth 2 "authorization code" flow. (This SDK does not support the "token" flow.) @@ -141,13 +142,13 @@ public class DbxWebAuth { private static final int CSRF_STRING_SIZE = StringUtil.urlSafeBase64Encode(new byte[CSRF_BYTES_SIZE]).length(); /** Role representing the team account associated with a user. Used by {@link Request.Builder#withRequireRole}. */ - public static final String ROLE_WORK = "work"; + public static final @Nonnull String ROLE_WORK = "work"; /** Role representing the personal account associated with a user. Used by {@link Request.Builder#withRequireRole}. */ - public static final String ROLE_PERSONAL = "personal"; + public static final @Nonnull String ROLE_PERSONAL = "personal"; - final DbxRequestConfig requestConfig; - final DbxAppInfo appInfo; - final Request deprecatedRequest; + final @Nonnull DbxRequestConfig requestConfig; + final @Nonnull DbxAppInfo appInfo; + final @Nullable Request deprecatedRequest; /** * Creates a new instance that will perform the OAuth2 authorization flow using a redirect URI. @@ -162,7 +163,10 @@ public class DbxWebAuth { * instead */ @Deprecated - public DbxWebAuth(DbxRequestConfig requestConfig, DbxAppInfo appInfo, String redirectUri, DbxSessionStore sessionStore) { + public DbxWebAuth(@Nonnull DbxRequestConfig requestConfig, + @Nonnull DbxAppInfo appInfo, + @Nonnull String redirectUri, + @Nonnull DbxSessionStore sessionStore) { if (requestConfig == null) throw new NullPointerException("requestConfig"); if (appInfo == null) throw new NullPointerException("appInfo"); @@ -182,7 +186,7 @@ public DbxWebAuth(DbxRequestConfig requestConfig, DbxAppInfo appInfo, String red * @param appInfo Your application's Dropbox API information (the app key and secret), never * {@code null}. */ - public DbxWebAuth(DbxRequestConfig requestConfig, DbxAppInfo appInfo) { + public DbxWebAuth(@Nonnull DbxRequestConfig requestConfig, @Nonnull DbxAppInfo appInfo) { if (requestConfig == null) throw new NullPointerException("requestConfig"); if (appInfo == null) throw new NullPointerException("appInfo"); @@ -214,7 +218,7 @@ public DbxWebAuth(DbxRequestConfig requestConfig, DbxAppInfo appInfo) { * instead. */ @Deprecated - public String start(/*@Nullable*/String urlState) { + public @Nonnull String start(@Nullable String urlState) { if (deprecatedRequest == null) { throw new IllegalStateException("Must use DbxWebAuth.authorize instead."); } @@ -248,7 +252,7 @@ public String start(/*@Nullable*/String urlState) { * constructor, or if this (@link DbxWebAuth} instance was created with {@link DbxAppInfo} * without app secret. */ - public String authorize(Request request) { + public @Nonnull String authorize(@Nonnull Request request) { if (deprecatedRequest != null) { throw new IllegalStateException("Must create this instance using DbxWebAuth(DbxRequestConfig,DbxAppInfo) to call this method."); } @@ -260,11 +264,12 @@ public String authorize(Request request) { return authorizeImpl(request); } - private String authorizeImpl(Request request) { + private @Nonnull String authorizeImpl(@Nonnull Request request) { return authorizeImpl(request, null); } - String authorizeImpl(Request request, Map pkceParams) { + @Nonnull + String authorizeImpl(@Nonnull Request request, @Nullable Map pkceParams) { Map params = new HashMap(); params.put("client_id", appInfo.getKey()); @@ -319,7 +324,7 @@ String authorizeImpl(Request request, Map pkceParams) { * * @throws DbxException if an error occurs communicating with Dropbox. */ - public DbxAuthFinish finishFromCode(String code) throws DbxException { + public @Nonnull DbxAuthFinish finishFromCode(@Nonnull String code) throws DbxException { return finish(code); } @@ -333,7 +338,7 @@ public DbxAuthFinish finishFromCode(String code) throws DbxException { * * @throws DbxException if an error occurs communicating with Dropbox. */ - public DbxAuthFinish finishFromCode(String code, String redirectUri) throws DbxException { + public @Nonnull DbxAuthFinish finishFromCode(@Nonnull String code, @Nonnull String redirectUri) throws DbxException { return finish(code, redirectUri, null); } @@ -359,17 +364,19 @@ public DbxAuthFinish finishFromCode(String code, String redirectUri) throws DbxE * set. * @throws DbxException If an error occurs communicating with Dropbox. */ - public DbxAuthFinish finishFromRedirect(String redirectUri, - DbxSessionStore sessionStore, - Map params) + public @Nonnull DbxAuthFinish finishFromRedirect(@Nonnull String redirectUri, + @Nonnull DbxSessionStore sessionStore, + @Nonnull Map params) throws DbxException, BadRequestException, BadStateException, CsrfException, NotApprovedException, ProviderException { - String strippedState = validateRedirectUri(redirectUri, sessionStore, params); + @Nullable String strippedState = validateRedirectUri(redirectUri, sessionStore, params); String code = getParam(params, "code"); return finish(code, redirectUri, strippedState); } - static String validateRedirectUri(String redirectUri, DbxSessionStore sessionStore, Map params) + static @Nullable String validateRedirectUri(@Nonnull String redirectUri, + @Nonnull DbxSessionStore sessionStore, + @Nonnull Map params) throws BadRequestException, BadStateException, CsrfException, NotApprovedException, ProviderException { if (redirectUri == null) throw new NullPointerException("redirectUri"); @@ -416,11 +423,12 @@ static String validateRedirectUri(String redirectUri, DbxSessionStore sessionSto return state; } - private DbxAuthFinish finish(String code) throws DbxException { + private @Nonnull DbxAuthFinish finish(@Nonnull String code) throws DbxException { return finish(code, null, null); } - DbxAuthFinish finish(String code, String redirectUri, final String state) throws + @Nonnull + DbxAuthFinish finish(@Nonnull String code, @Nullable String redirectUri, final @Nullable String state) throws DbxException { if (code == null) throw new NullPointerException("code"); if (!appInfo.hasSecret()) { @@ -437,7 +445,11 @@ DbxAuthFinish finish(String code, String redirectUri, final String state) throws } List headers = new ArrayList(); - DbxRequestUtil.addBasicAuthHeader(headers, appInfo.getKey(), appInfo.getSecret()); + String appSecret = appInfo.getSecret(); + if (appSecret == null) { + throw new IllegalStateException("App secret is required for non-PKCE OAuth."); + } + DbxRequestUtil.addBasicAuthHeader(headers, appInfo.getKey(), appSecret); return DbxRequestUtil.doPostNoAuth( requestConfig, @@ -448,7 +460,7 @@ DbxAuthFinish finish(String code, String redirectUri, final String state) throws headers, new DbxRequestUtil.ResponseHandler() { @Override - public DbxAuthFinish handle(HttpRequestor.Response response) throws DbxException { + public @Nonnull DbxAuthFinish handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) { throw DbxRequestUtil.unexpectedStatus(response); } @@ -481,7 +493,7 @@ public DbxAuthFinish handle(HttpRequestor.Response response) throws DbxException * @deprecated use {@link #finishFromRedirect finishFromRedirect(..)} instead. */ @Deprecated - public DbxAuthFinish finish(Map queryParams) + public @Nonnull DbxAuthFinish finish(@Nonnull Map queryParams) throws DbxException, BadRequestException, BadStateException, CsrfException, NotApprovedException, ProviderException { if (deprecatedRequest == null) { throw new IllegalStateException("Must use DbxWebAuth.finishFromRedirect(..) instead."); @@ -493,7 +505,7 @@ public DbxAuthFinish finish(Map queryParams) ); } - private static String appendCsrfToken(Request request) { + private static @Nonnull String appendCsrfToken(@Nonnull Request request) { // add a CSRF nonce for security byte[] csrf = new byte[CSRF_BYTES_SIZE]; RAND.nextBytes(csrf); @@ -518,7 +530,7 @@ private static String appendCsrfToken(Request request) { } } - private static String verifyAndStripCsrfToken(String state, DbxSessionStore sessionStore) + private static @Nullable String verifyAndStripCsrfToken(@Nonnull String state, @Nonnull DbxSessionStore sessionStore) throws CsrfException, BadStateException { String expected = sessionStore.get(); if (expected == null) { @@ -544,7 +556,7 @@ private static String verifyAndStripCsrfToken(String state, DbxSessionStore sess return stripped.isEmpty() ? null : stripped; } - static /*@Nullable*/String getParam(Map params, String name) throws BadRequestException { + static @Nullable String getParam(@Nonnull Map params, @Nonnull String name) throws BadRequestException { String[] v = params.get(name); if (v == null) { @@ -564,7 +576,7 @@ private static String verifyAndStripCsrfToken(String state, DbxSessionStore sess */ public static abstract class Exception extends java.lang.Exception { private static final long serialVersionUID = 0L; - public Exception(String message) { super(message); } + public Exception(@Nonnull String message) { super(message); } } /** @@ -580,7 +592,7 @@ public static abstract class Exception extends java.lang.Exception { */ public static final class BadRequestException extends Exception { private static final long serialVersionUID = 0L; - public BadRequestException(String message) { super(message); } + public BadRequestException(@Nonnull String message) { super(message); } } /** @@ -598,7 +610,7 @@ public static final class BadRequestException extends Exception { */ public static final class BadStateException extends Exception { private static final long serialVersionUID = 0L; - public BadStateException(String message) { super(message); } + public BadStateException(@Nonnull String message) { super(message); } } /** @@ -615,7 +627,7 @@ public static final class BadStateException extends Exception { */ public static final class CsrfException extends Exception { private static final long serialVersionUID = 0L; - public CsrfException(String message) { super(message); } + public CsrfException(@Nonnull String message) { super(message); } } /** @@ -628,7 +640,7 @@ public static final class CsrfException extends Exception { */ public static final class NotApprovedException extends Exception { private static final long serialVersionUID = 0L; - public NotApprovedException(String message) { super(message); } + public NotApprovedException(@Nonnull String message) { super(message); } } /** @@ -640,7 +652,7 @@ public static final class NotApprovedException extends Exception { */ public static final class ProviderException extends Exception { private static final long serialVersionUID = 0L; - public ProviderException(String message) { super(message); } + public ProviderException(@Nonnull String message) { super(message); } } /** @@ -648,7 +660,7 @@ public static final class ProviderException extends Exception { * * @return new request builder with default values */ - public static Request.Builder newRequestBuilder() { + public static @Nonnull Request.Builder newRequestBuilder() { return Request.newBuilder(); } @@ -661,26 +673,26 @@ public static final class Request { private static final Charset UTF8 = Charset.forName("UTF-8"); private static final int MAX_STATE_SIZE = 500; - private final String redirectUri; - private final String state; - private final String requireRole; - private final Boolean forceReapprove; - private final Boolean disableSignup; - private final DbxSessionStore sessionStore; - private final TokenAccessType tokenAccessType; - private final String scope; - private final IncludeGrantedScopes includeGrantedScopes; - - - private Request(String redirectUri, - String state, - String requireRole, - Boolean forceReapprove, - Boolean disableSignup, - DbxSessionStore sessionStore, - TokenAccessType tokenAccessType, - String scope, - IncludeGrantedScopes includeGrantedScopes) { + private final @Nullable String redirectUri; + private final @Nullable String state; + private final @Nullable String requireRole; + private final @Nullable Boolean forceReapprove; + private final @Nullable Boolean disableSignup; + private final @Nullable DbxSessionStore sessionStore; + private final @Nullable TokenAccessType tokenAccessType; + private final @Nullable String scope; + private final @Nullable IncludeGrantedScopes includeGrantedScopes; + + + private Request(@Nullable String redirectUri, + @Nullable String state, + @Nullable String requireRole, + @Nullable Boolean forceReapprove, + @Nullable Boolean disableSignup, + @Nullable DbxSessionStore sessionStore, + @Nullable TokenAccessType tokenAccessType, + @Nullable String scope, + @Nullable IncludeGrantedScopes includeGrantedScopes) { this.redirectUri = redirectUri; this.state = state; this.requireRole = requireRole; @@ -697,7 +709,7 @@ private Request(String redirectUri, * * @return copy of this request */ - public Builder copy() { + public @Nonnull Builder copy() { return new Builder( redirectUri, state, @@ -716,7 +728,7 @@ public Builder copy() { * * @return new request builder with default values */ - public static Builder newBuilder() { + public static @Nonnull Builder newBuilder() { return new Builder(); } @@ -724,29 +736,29 @@ public static Builder newBuilder() { * Builder for OAuth2 requests. Use this builder to configure the OAuth authorization flow. */ public static final class Builder { - private String redirectUri; - private String state; - private String requireRole; - private Boolean forceReapprove; - private Boolean disableSignup; - private DbxSessionStore sessionStore; - private TokenAccessType tokenAccessType; - private String scope; - private IncludeGrantedScopes includeGrantedScopes; + private @Nullable String redirectUri; + private @Nullable String state; + private @Nullable String requireRole; + private @Nullable Boolean forceReapprove; + private @Nullable Boolean disableSignup; + private @Nullable DbxSessionStore sessionStore; + private @Nullable TokenAccessType tokenAccessType; + private @Nullable String scope; + private @Nullable IncludeGrantedScopes includeGrantedScopes; private Builder() { this(null, null, null, null, null, null, null, null, null); } - private Builder(String redirectUri, - String state, - String requireRole, - Boolean forceReapprove, - Boolean disableSignup, - DbxSessionStore sessionStore, - TokenAccessType tokenAccessType, - String scope, - IncludeGrantedScopes includeGrantedScopes) { + private Builder(@Nullable String redirectUri, + @Nullable String state, + @Nullable String requireRole, + @Nullable Boolean forceReapprove, + @Nullable Boolean disableSignup, + @Nullable DbxSessionStore sessionStore, + @Nullable TokenAccessType tokenAccessType, + @Nullable String scope, + @Nullable IncludeGrantedScopes includeGrantedScopes) { this.redirectUri = redirectUri; this.state = state; this.requireRole = requireRole; @@ -768,7 +780,7 @@ private Builder(String redirectUri, * * @return this builder */ - public Builder withNoRedirect() { + public @Nonnull Builder withNoRedirect() { this.redirectUri = null; this.sessionStore = null; return this; @@ -797,7 +809,7 @@ public Builder withNoRedirect() { * * @throws NullPointerException if either redirectUri or sessionStore is {@code null} */ - public Builder withRedirectUri(String redirectUri, DbxSessionStore sessionStore) { + public @Nonnull Builder withRedirectUri(@Nonnull String redirectUri, @Nonnull DbxSessionStore sessionStore) { if (redirectUri == null) throw new NullPointerException("redirectUri"); if (sessionStore == null) throw new NullPointerException("sessionStore"); @@ -824,7 +836,7 @@ public Builder withRedirectUri(String redirectUri, DbxSessionStore sessionStore) * * @throws IllegalArgumentException if state is greater than 476 bytes */ - public Builder withState(String state) { + public @Nonnull Builder withState(@Nullable String state) { if (state != null && (state.getBytes(UTF8).length + CSRF_STRING_SIZE) > MAX_STATE_SIZE) { throw new IllegalArgumentException("UTF-8 encoded state cannot be greater than " + (MAX_STATE_SIZE - CSRF_STRING_SIZE) + " bytes."); } @@ -846,7 +858,7 @@ public Builder withState(String state) { * @see DbxWebAuth#ROLE_WORK * @see DbxWebAuth#ROLE_PERSONAL */ - public Builder withRequireRole(String requireRole) { + public @Nonnull Builder withRequireRole(@Nullable String requireRole) { this.requireRole = requireRole; return this; } @@ -864,7 +876,7 @@ public Builder withRequireRole(String requireRole) { * @param forceReapprove whether to force a user to re-approve this app, or {@code null} * for default behavior */ - public Builder withForceReapprove(Boolean forceReapprove) { + public @Nonnull Builder withForceReapprove(@Nullable Boolean forceReapprove) { this.forceReapprove = forceReapprove; return this; } @@ -882,7 +894,7 @@ public Builder withForceReapprove(Boolean forceReapprove) { * * @return this builder */ - public Builder withDisableSignup(Boolean disableSignup) { + public @Nonnull Builder withDisableSignup(@Nullable Boolean disableSignup) { this.disableSignup = disableSignup; return this; } @@ -902,7 +914,7 @@ public Builder withDisableSignup(Boolean disableSignup) { * * @return this builder */ - public Builder withTokenAccessType(TokenAccessType tokenAccessType) { + public @Nonnull Builder withTokenAccessType(@Nullable TokenAccessType tokenAccessType) { this.tokenAccessType = tokenAccessType; return this; } @@ -914,7 +926,7 @@ public Builder withTokenAccessType(TokenAccessType tokenAccessType) { * API endpoints. To call one API endpoint you have to obtains the scope first otherwise you * will get HTTP 401. Example: "account_info.read files.content.read" */ - public Builder withScope(Collection scope) { + public @Nonnull Builder withScope(@Nullable Collection scope) { if (scope != null) { this.scope = StringUtil.join(scope, " "); } @@ -931,7 +943,7 @@ public Builder withScope(Collection scope) { * scopes user previously granted your app together with * the new scopes. */ - public Builder withIncludeGrantedScopes(IncludeGrantedScopes includeGrantedScopes) { + public @Nonnull Builder withIncludeGrantedScopes(@Nullable IncludeGrantedScopes includeGrantedScopes) { this.includeGrantedScopes = includeGrantedScopes; return this; } @@ -945,7 +957,7 @@ public Builder withIncludeGrantedScopes(IncludeGrantedScopes includeGrantedScope * @throws IllegalStateException if {@link #withState} was called with a non-{@code * null} value, but no redirect URI was specified. */ - public Request build() { + public @Nonnull Request build() { if (redirectUri == null && state != null) { throw new IllegalStateException("Cannot specify a state without a redirect URI."); } diff --git a/core/src/main/java/com/dropbox/core/DbxWebAuthNoRedirect.java b/core/src/main/java/com/dropbox/core/DbxWebAuthNoRedirect.java index ad208e56e..6b69e0449 100644 --- a/core/src/main/java/com/dropbox/core/DbxWebAuthNoRedirect.java +++ b/core/src/main/java/com/dropbox/core/DbxWebAuthNoRedirect.java @@ -2,6 +2,8 @@ import com.dropbox.core.v2.DbxClientV2; +import javax.annotation.Nonnull; + /** * Does the OAuth web-based authorization flow for apps that can't provide a redirect URI (such as * the command-line example apps that come with this SDK). If you're a normal website, use the @@ -47,13 +49,13 @@ */ @Deprecated public class DbxWebAuthNoRedirect { - private final DbxWebAuth auth; + private final @Nonnull DbxWebAuth auth; /** * @param appInfo * Your application's Dropbox API information (the app key and secret). */ - public DbxWebAuthNoRedirect(DbxRequestConfig requestConfig, DbxAppInfo appInfo) { + public DbxWebAuthNoRedirect(@Nonnull DbxRequestConfig requestConfig, @Nonnull DbxAppInfo appInfo) { this.auth = new DbxWebAuth(requestConfig, appInfo); } @@ -67,7 +69,7 @@ public DbxWebAuthNoRedirect(DbxRequestConfig requestConfig, DbxAppInfo appInfo) * access token. *

*/ - public String start() { + public @Nonnull String start() { DbxWebAuth.Request request = DbxWebAuth.newRequestBuilder() .withNoRedirect() .build(); @@ -82,7 +84,7 @@ public String start() { * The authorization code shown to the user when they clicked "Allow" on the authorization * page on the Dropbox website. */ - public DbxAuthFinish finish(String code) throws DbxException { + public @Nonnull DbxAuthFinish finish(@Nonnull String code) throws DbxException { return auth.finishFromCode(code); } } diff --git a/core/src/main/java/com/dropbox/core/DbxWrappedException.java b/core/src/main/java/com/dropbox/core/DbxWrappedException.java index d7ea999a7..569545b40 100644 --- a/core/src/main/java/com/dropbox/core/DbxWrappedException.java +++ b/core/src/main/java/com/dropbox/core/DbxWrappedException.java @@ -11,35 +11,42 @@ import com.dropbox.core.v2.callbacks.DbxGlobalCallbackFactory; import com.dropbox.core.v2.callbacks.DbxRouteErrorCallback; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * For internal use only. */ public final class DbxWrappedException extends Exception { private static final long serialVersionUID = 0L; - private final Object errValue; // Really an ErrT instance, but Throwable does not allow generic subclasses. - private final String requestId; - private final LocalizedText userMessage; + private final @Nonnull Object errValue; // Really an ErrT instance, but Throwable does not allow generic subclasses. + private final @Nullable String requestId; + private final @Nullable LocalizedText userMessage; - public DbxWrappedException(Object errValue, String requestId, LocalizedText userMessage) { + public DbxWrappedException(@Nonnull Object errValue, + @Nullable String requestId, + @Nullable LocalizedText userMessage) { this.errValue = errValue; this.requestId = requestId; this.userMessage = userMessage; } - public Object getErrorValue() { + public @Nonnull Object getErrorValue() { return errValue; } - public String getRequestId() { + public @Nullable String getRequestId() { return requestId; } - public LocalizedText getUserMessage() { + public @Nullable LocalizedText getUserMessage() { return userMessage; } - public static DbxWrappedException fromResponse(StoneSerializer errSerializer, HttpRequestor.Response response, String userId) + public static @Nonnull DbxWrappedException fromResponse(@Nonnull StoneSerializer errSerializer, + @Nonnull HttpRequestor.Response response, + @Nullable String userId) throws IOException, JsonParseException { String requestId = DbxRequestUtil.getRequestId(response); @@ -55,7 +62,9 @@ public static DbxWrappedException fromResponse(StoneSerializer errSeriali return new DbxWrappedException(routeError, requestId, apiResponse.getUserMessage()); } - public static void executeOtherBlocks(DbxGlobalCallbackFactory factory, String userId, Object routeError) { + public static void executeOtherBlocks(@Nullable DbxGlobalCallbackFactory factory, + @Nullable String userId, + @Nullable Object routeError) { try { // Recursively looks at union errors and the union's current tag type. If there is a handler // for the current tag type, it is executed. @@ -75,7 +84,9 @@ public static void executeOtherBlocks(DbxGlobalCallbackFactory factory, String u } } - public static void executeBlockForObject(DbxGlobalCallbackFactory factory, String userId, T routeError) { + public static void executeBlockForObject(@Nullable DbxGlobalCallbackFactory factory, + @Nullable String userId, + @Nullable T routeError) { if (factory != null) { DbxRouteErrorCallback callback = factory.createRouteErrorCallback(userId, routeError); if (callback != null) { diff --git a/core/src/main/java/com/dropbox/core/IncludeGrantedScopes.java b/core/src/main/java/com/dropbox/core/IncludeGrantedScopes.java index 8ccc60f6f..3fb82c721 100644 --- a/core/src/main/java/com/dropbox/core/IncludeGrantedScopes.java +++ b/core/src/main/java/com/dropbox/core/IncludeGrantedScopes.java @@ -1,5 +1,7 @@ package com.dropbox.core; +import javax.annotation.Nonnull; + /** * If this field is present, Dropbox server will return a token with all scopes user previously * granted your app. @@ -17,7 +19,7 @@ public enum IncludeGrantedScopes { TEAM; @Override - public String toString() { + public @Nonnull String toString() { return this.name().toLowerCase(); } } diff --git a/core/src/main/java/com/dropbox/core/InvalidAccessTokenException.java b/core/src/main/java/com/dropbox/core/InvalidAccessTokenException.java index 015efa101..3c52502f2 100644 --- a/core/src/main/java/com/dropbox/core/InvalidAccessTokenException.java +++ b/core/src/main/java/com/dropbox/core/InvalidAccessTokenException.java @@ -2,6 +2,9 @@ import com.dropbox.core.v2.auth.AuthError; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Gets thrown when the access token you're using to make API calls is invalid. * @@ -15,14 +18,16 @@ */ public class InvalidAccessTokenException extends DbxException { private static final long serialVersionUID = 0; - private AuthError authError; + private @Nonnull AuthError authError; - public InvalidAccessTokenException(String requestId, String message, AuthError authError) { + public InvalidAccessTokenException(@Nullable String requestId, + @Nullable String message, + @Nonnull AuthError authError) { super(requestId, message); this.authError = authError; } - public AuthError getAuthError() { + public @Nonnull AuthError getAuthError() { return this.authError; } } diff --git a/core/src/main/java/com/dropbox/core/LocalizedText.java b/core/src/main/java/com/dropbox/core/LocalizedText.java index 63de27e9b..8d1ffd9f6 100644 --- a/core/src/main/java/com/dropbox/core/LocalizedText.java +++ b/core/src/main/java/com/dropbox/core/LocalizedText.java @@ -11,12 +11,14 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonToken; +import javax.annotation.Nonnull; + /** * Human-readable text localized to a specific locale. */ public final class LocalizedText { - private final String text; - private final String locale; + private final @Nonnull String text; + private final @Nonnull String locale; /** * Create a {@link LocalizedText} object that contains the given {@code text} already localized @@ -25,7 +27,7 @@ public final class LocalizedText { * @param text Localized, human-readable text. Must not be {@code null} * @param locale IETF BCP 47 language tag of text locale. Must not be {@code null} */ - public LocalizedText(String text, String locale) { + public LocalizedText(@Nonnull String text, @Nonnull String locale) { if (text == null) { throw new NullPointerException("text"); } @@ -42,7 +44,7 @@ public LocalizedText(String text, String locale) { * * @return localized, human-readable text, never {@code null} */ - public String getText() { + public @Nonnull String getText() { return text; } @@ -51,12 +53,12 @@ public String getText() { * * @return locale of text in IETF BCP 47 language tag format, never {@code null} */ - public String getLocale() { + public @Nonnull String getLocale() { return locale; } @Override - public String toString() { + public @Nonnull String toString() { return text; } @@ -65,12 +67,12 @@ public String toString() { */ static final StoneSerializer STONE_SERIALIZER = new StoneSerializer() { @Override - public void serialize(LocalizedText value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nonnull LocalizedText value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { throw new UnsupportedOperationException("Error wrapper serialization not supported."); } @Override - public LocalizedText deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull LocalizedText deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { String text = null; String locale = null; diff --git a/core/src/main/java/com/dropbox/core/NetworkIOException.java b/core/src/main/java/com/dropbox/core/NetworkIOException.java index 9b54b120d..98aab8c98 100644 --- a/core/src/main/java/com/dropbox/core/NetworkIOException.java +++ b/core/src/main/java/com/dropbox/core/NetworkIOException.java @@ -3,6 +3,8 @@ import javax.net.ssl.SSLHandshakeException; import java.io.IOException; import java.security.cert.CertPathValidatorException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * This gets thrown when there's an {@link IOException} when reading or writing to the @@ -15,12 +17,15 @@ public class NetworkIOException extends DbxException { private static final long serialVersionUID = 0L; - public NetworkIOException(IOException cause) { + public NetworkIOException(@Nonnull IOException cause) { super(computeMessage(cause), cause); } - private static String computeMessage(IOException ex) { - String message = ex.getMessage(); + private static @Nonnull String computeMessage(@Nonnull IOException ex) { + @Nullable String message = ex.getMessage(); + if (message == null) { + message = ex.toString(); + } // For CertPathValidationErrors, the CertPath is in the exception object but not // in the exception message. Pull it out into the message, because it would be @@ -37,9 +42,8 @@ private static String computeMessage(IOException ex) { } @Override - public IOException getCause() { + public @Nonnull IOException getCause() { // guaranteed to be an IOException return (IOException) super.getCause(); } } - diff --git a/core/src/main/java/com/dropbox/core/NoThrowInputStream.java b/core/src/main/java/com/dropbox/core/NoThrowInputStream.java index 731cd9071..238b2117f 100644 --- a/core/src/main/java/com/dropbox/core/NoThrowInputStream.java +++ b/core/src/main/java/com/dropbox/core/NoThrowInputStream.java @@ -4,6 +4,8 @@ import java.io.InputStream; import java.io.OutputStream; +import javax.annotation.Nonnull; + /** * Wraps an existing input stream, converting all the underlying stream's {@code IOException}s * to our own {@link HiddenException}, which is a subclass of {@code RuntimeException}. This @@ -21,10 +23,10 @@ *

*/ public final class NoThrowInputStream extends InputStream { - private final InputStream underlying; + private final @Nonnull InputStream underlying; private long bytesRead = 0; - public NoThrowInputStream(InputStream underlying) { + public NoThrowInputStream(@Nonnull InputStream underlying) { this.underlying = underlying; } @@ -44,7 +46,7 @@ public int read() { } @Override - public int read(byte[] b, int off, int len) { + public int read(@Nonnull byte[] b, int off, int len) { try { int bytesReadNow = underlying.read(b, off, len); this.bytesRead += bytesReadNow; @@ -56,7 +58,7 @@ public int read(byte[] b, int off, int len) { } @Override - public int read(byte[] b) { + public int read(@Nonnull byte[] b) { try { int bytesReadNow = underlying.read(b); this.bytesRead += bytesReadNow; @@ -69,12 +71,12 @@ public int read(byte[] b) { public static final class HiddenException extends RuntimeException { private static final long serialVersionUID = 0L; - public HiddenException(IOException underlying) { + public HiddenException(@Nonnull IOException underlying) { super(underlying); } @Override - public IOException getCause() { + public @Nonnull IOException getCause() { return (IOException) super.getCause(); } } diff --git a/core/src/main/java/com/dropbox/core/NoThrowOutputStream.java b/core/src/main/java/com/dropbox/core/NoThrowOutputStream.java index 6bf2175a2..269da3d2a 100644 --- a/core/src/main/java/com/dropbox/core/NoThrowOutputStream.java +++ b/core/src/main/java/com/dropbox/core/NoThrowOutputStream.java @@ -3,6 +3,8 @@ import java.io.IOException; import java.io.OutputStream; +import javax.annotation.Nonnull; + /** * Wraps an existing output stream, converting all the underlying stream's {@code IOException}s * to our own {@link HiddenException}, which is a subclass of {@code RuntimeException}. This @@ -21,10 +23,10 @@ */ public final class NoThrowOutputStream extends OutputStream { - private final OutputStream underlying; + private final @Nonnull OutputStream underlying; private long bytesWritten = 0; - public NoThrowOutputStream(OutputStream underlying) + public NoThrowOutputStream(@Nonnull OutputStream underlying) { this.underlying = underlying; } @@ -47,7 +49,7 @@ public void flush() } @Override - public void write(byte[] b, int off, int len) + public void write(@Nonnull byte[] b, int off, int len) { try { bytesWritten += len; @@ -59,7 +61,7 @@ public void write(byte[] b, int off, int len) } @Override - public void write(byte[] b) + public void write(@Nonnull byte[] b) { try { bytesWritten += b.length; @@ -84,16 +86,16 @@ public void write(int b) public static final class HiddenException extends RuntimeException { - public final NoThrowOutputStream owner; + public final @Nonnull NoThrowOutputStream owner; - public HiddenException(NoThrowOutputStream owner, IOException underlying) + public HiddenException(@Nonnull NoThrowOutputStream owner, @Nonnull IOException underlying) { super(underlying); this.owner = owner; } @Override - public IOException getCause() + public @Nonnull IOException getCause() { return (IOException) super.getCause(); } diff --git a/core/src/main/java/com/dropbox/core/PathRootErrorException.java b/core/src/main/java/com/dropbox/core/PathRootErrorException.java index 8a4acde97..b25aadf9b 100644 --- a/core/src/main/java/com/dropbox/core/PathRootErrorException.java +++ b/core/src/main/java/com/dropbox/core/PathRootErrorException.java @@ -2,19 +2,24 @@ import com.dropbox.core.v2.common.PathRootError; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Gets thrown when an invalid path rood is supplied. */ public class PathRootErrorException extends DbxException { private static final long serialVersionUID = 0; - private final PathRootError pathRootError; + private final @Nonnull PathRootError pathRootError; - public PathRootError getPathRootError() { + public @Nonnull PathRootError getPathRootError() { return pathRootError; } - public PathRootErrorException(String requestId, String message, PathRootError pathRootError) { + public PathRootErrorException(@Nullable String requestId, + @Nullable String message, + @Nonnull PathRootError pathRootError) { super(requestId, message); this.pathRootError = pathRootError; } diff --git a/core/src/main/java/com/dropbox/core/ProtocolException.java b/core/src/main/java/com/dropbox/core/ProtocolException.java index 54775f9bd..d0bf7756e 100644 --- a/core/src/main/java/com/dropbox/core/ProtocolException.java +++ b/core/src/main/java/com/dropbox/core/ProtocolException.java @@ -1,5 +1,8 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Something unexpected happened with either the request or the response. * This can happen if there's a bug in the client code (including this @@ -15,12 +18,11 @@ public abstract class ProtocolException extends DbxException { private static final long serialVersionUID = 0; - public ProtocolException(String requestId, String message) { + public ProtocolException(@Nullable String requestId, @Nullable String message) { super(requestId, message); } - public ProtocolException(String requestId, String message, Throwable cause) { + public ProtocolException(@Nullable String requestId, @Nullable String message, @Nonnull Throwable cause) { super(requestId, message, cause); } } - diff --git a/core/src/main/java/com/dropbox/core/RateLimitException.java b/core/src/main/java/com/dropbox/core/RateLimitException.java index 0c35c50f3..12234b885 100644 --- a/core/src/main/java/com/dropbox/core/RateLimitException.java +++ b/core/src/main/java/com/dropbox/core/RateLimitException.java @@ -2,6 +2,9 @@ import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * The server is overloaded, or you have hit a rate limit. Try again later after the designated * backoff (see {@link #getBackoffMillis}). @@ -9,8 +12,7 @@ public class RateLimitException extends RetryException { private static final long serialVersionUID = 0L; - public RateLimitException(String requestId, String message, long backoff, TimeUnit unit) { + public RateLimitException(@Nullable String requestId, @Nullable String message, long backoff, @Nonnull TimeUnit unit) { super(requestId, message, backoff, unit); } } - diff --git a/core/src/main/java/com/dropbox/core/RetryException.java b/core/src/main/java/com/dropbox/core/RetryException.java index 7d61ce151..1ec63122a 100644 --- a/core/src/main/java/com/dropbox/core/RetryException.java +++ b/core/src/main/java/com/dropbox/core/RetryException.java @@ -2,6 +2,9 @@ import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * A transient exception has occurred and the request should be retried. Clients should only retry * requests after waiting the requested backoff duration (see {@link #getBackoffMillis}). @@ -17,7 +20,7 @@ public class RetryException extends DbxException { * @param requestId ID assigned to request by Dropbox servers * @param message Error message */ - public RetryException(String requestId, String message) { + public RetryException(@Nullable String requestId, @Nullable String message) { this(requestId, message, 0L, TimeUnit.MILLISECONDS); } @@ -29,7 +32,7 @@ public RetryException(String requestId, String message) { * @param backoff amount of time to backoff before retrying the request * @param unit unit of time for {@code backoff} */ - public RetryException(String requestId, String message, long backoff, TimeUnit unit) { + public RetryException(@Nullable String requestId, @Nullable String message, long backoff, @Nonnull TimeUnit unit) { super(requestId, message); this.backoffMillis = unit.toMillis(backoff); @@ -45,4 +48,3 @@ public long getBackoffMillis() { return backoffMillis; } } - diff --git a/core/src/main/java/com/dropbox/core/ServerException.java b/core/src/main/java/com/dropbox/core/ServerException.java index b4948c0e1..6d2c44887 100644 --- a/core/src/main/java/com/dropbox/core/ServerException.java +++ b/core/src/main/java/com/dropbox/core/ServerException.java @@ -1,5 +1,8 @@ package com.dropbox.core; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * The server said that something went wrong on its end (HTTP 500 error code). * This indicates bug on the Dropbox server, but there are multiple potential causes. @@ -26,8 +29,7 @@ public class ServerException extends DbxException { private static final long serialVersionUID = 0; - public ServerException(String requestId, String message) { + public ServerException(@Nullable String requestId, @Nullable String message) { super(requestId, message); } } - diff --git a/core/src/main/java/com/dropbox/core/TokenAccessType.java b/core/src/main/java/com/dropbox/core/TokenAccessType.java index 15a73dfe0..05772a70b 100644 --- a/core/src/main/java/com/dropbox/core/TokenAccessType.java +++ b/core/src/main/java/com/dropbox/core/TokenAccessType.java @@ -1,5 +1,7 @@ package com.dropbox.core; +import javax.annotation.Nonnull; + /** * Whether or not to include refresh token in {@link DbxAuthFinish} * Non-mobile apps use it in {@link DbxWebAuth}. @@ -15,14 +17,14 @@ public enum TokenAccessType{ */ OFFLINE("offline"); - private String string; + private @Nonnull String string; - TokenAccessType(String string) { + TokenAccessType(@Nonnull String string) { this.string = string; } @Override - public String toString() { + public @Nonnull String toString() { return string; } } diff --git a/core/src/main/java/com/dropbox/core/http/GoogleAppEngineRequestor.java b/core/src/main/java/com/dropbox/core/http/GoogleAppEngineRequestor.java index 5a513f7a9..02e835bf8 100644 --- a/core/src/main/java/com/dropbox/core/http/GoogleAppEngineRequestor.java +++ b/core/src/main/java/com/dropbox/core/http/GoogleAppEngineRequestor.java @@ -19,7 +19,9 @@ import com.google.appengine.api.urlfetch.URLFetchService; import com.google.appengine.api.urlfetch.URLFetchServiceFactory; -/*>>> import checkers.nullness.quals.Nullable; */ +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * {@link HttpRequestor} implementation that uses Google App Engine URL fetch service. @@ -47,45 +49,45 @@ public GoogleAppEngineRequestor() { this(newDefaultOptions()); } - public GoogleAppEngineRequestor(FetchOptions options) { + public GoogleAppEngineRequestor(@Nonnull FetchOptions options) { this(options, URLFetchServiceFactory.getURLFetchService()); } - public GoogleAppEngineRequestor(FetchOptions options, URLFetchService service) { + public GoogleAppEngineRequestor(@Nonnull FetchOptions options, @Nonnull URLFetchService service) { if (options == null) throw new NullPointerException("options"); if (service == null) throw new NullPointerException("service"); this.options = options; this.service = service; } - public FetchOptions getOptions() { + public @Nonnull FetchOptions getOptions() { return options; } - public URLFetchService getService() { + public @Nonnull URLFetchService getService() { return service; } @Override - public Response doGet(String url, Iterable
headers) throws IOException { + public @Nonnull Response doGet(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { HTTPRequest request = newRequest(url, HTTPMethod.GET, headers); HTTPResponse response = service.fetch(request); return toRequestorResponse(response); } @Override - public Uploader startPost(String url, Iterable
headers) throws IOException { + public @Nonnull Uploader startPost(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { HTTPRequest request = newRequest(url, HTTPMethod.POST, headers); return new FetchServiceUploader(service, request, new ByteArrayOutputStream()); } @Override - public Uploader startPut(String url, Iterable
headers) throws IOException { + public @Nonnull Uploader startPut(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { HTTPRequest request = newRequest(url, HTTPMethod.POST, headers); return new FetchServiceUploader(service, request, new ByteArrayOutputStream()); } - private HTTPRequest newRequest(String url, HTTPMethod method, Iterable
headers) throws IOException { + private @Nonnull HTTPRequest newRequest(@Nonnull String url, @Nonnull HTTPMethod method, @Nonnull Iterable
headers) throws IOException { HTTPRequest request = new HTTPRequest(new URL(url), method, options); for (Header header : headers) { request.addHeader(new HTTPHeader(header.getKey(), header.getValue())); @@ -99,7 +101,7 @@ private HTTPRequest newRequest(String url, HTTPMethod method, Iterable
h * * @return new instance of default fetch options used by this requestor. */ - public static FetchOptions newDefaultOptions() { + public static @Nonnull FetchOptions newDefaultOptions() { return FetchOptions.Builder.withDefaults() .validateCertificate() .doNotFollowRedirects() @@ -108,7 +110,7 @@ public static FetchOptions newDefaultOptions() { .setDeadline((DEFAULT_CONNECT_TIMEOUT_MILLIS + DEFAULT_READ_TIMEOUT_MILLIS)/1000.0); } - private static Response toRequestorResponse(HTTPResponse response) { + private static @Nonnull Response toRequestorResponse(@Nonnull HTTPResponse response) { Map> headers = new HashMap>(); for (HTTPHeader header : response.getHeadersUncombined()) { List existing = headers.get(header.getName()); @@ -128,16 +130,18 @@ private static class FetchServiceUploader extends Uploader { private final URLFetchService service; private final ByteArrayOutputStream body; - private HTTPRequest request; + private @Nullable HTTPRequest request; - public FetchServiceUploader(URLFetchService service, HTTPRequest request, ByteArrayOutputStream body) { + public FetchServiceUploader(@Nonnull URLFetchService service, + @Nonnull HTTPRequest request, + @Nonnull ByteArrayOutputStream body) { this.service = service; this.request = request; this.body = body; } @Override - public OutputStream getBody() { + public @Nonnull OutputStream getBody() { return body; } @@ -165,16 +169,17 @@ public void abort() { } @Override - public Response finish() throws IOException { + public @Nonnull Response finish() throws IOException { if (request == null) { throw new IllegalStateException("Uploader already closed."); } - request.setPayload(body.toByteArray()); + byte[] payload = body.toByteArray(); + request.setPayload(payload); HTTPResponse response = service.fetch(request); Response requestorResponse = toRequestorResponse(response); close(); if (progressListener != null) { - progressListener.onProgress(request.getPayload().length); + progressListener.onProgress(payload.length); } return requestorResponse; } diff --git a/core/src/main/java/com/dropbox/core/http/HttpRequestor.java b/core/src/main/java/com/dropbox/core/http/HttpRequestor.java index 8a23d0790..a4be27b62 100644 --- a/core/src/main/java/com/dropbox/core/http/HttpRequestor.java +++ b/core/src/main/java/com/dropbox/core/http/HttpRequestor.java @@ -14,6 +14,9 @@ import com.dropbox.core.util.IOUtil; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * An interface that the Dropbox client library uses to make HTTP requests. * If you're fine with the standard Java {@link java.net.HttpURLConnection} @@ -36,12 +39,12 @@ public abstract class HttpRequestor // server. public static final long DEFAULT_READ_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(2); - public abstract Response doGet(String url, Iterable
headers) throws IOException; - public abstract Uploader startPost(String url, Iterable
headers) throws IOException; - public Uploader startPostInStreamingMode(String url, Iterable
headers) throws IOException { + public abstract @Nonnull Response doGet(@Nonnull String url, @Nonnull Iterable
headers) throws IOException; + public abstract @Nonnull Uploader startPost(@Nonnull String url, @Nonnull Iterable
headers) throws IOException; + public @Nonnull Uploader startPostInStreamingMode(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { return startPost(url, headers); } - public abstract Uploader startPut(String url, Iterable
headers) throws IOException; + public abstract @Nonnull Uploader startPut(@Nonnull String url, @Nonnull Iterable
headers) throws IOException; /** * A simple structure holding an HTTP header, which is key/value pair. @@ -51,7 +54,7 @@ public static final class Header { private final String key; private final String value; - public Header(String key, String value) { + public Header(@Nonnull String key, @Nonnull String value) { this.key = key; this.value = value; } @@ -61,7 +64,7 @@ public Header(String key, String value) { * * @return header name */ - public String getKey() { + public @Nonnull String getKey() { return key; } @@ -70,20 +73,20 @@ public String getKey() { * * @return header value */ - public String getValue() { + public @Nonnull String getValue() { return value; } } public static abstract class Uploader { - protected IOUtil.ProgressListener progressListener; + protected @Nullable IOUtil.ProgressListener progressListener; - public abstract OutputStream getBody(); + public abstract @Nonnull OutputStream getBody(); public abstract void close(); public abstract void abort(); - public abstract Response finish() throws IOException; + public abstract @Nonnull Response finish() throws IOException; - public void upload(File file) throws IOException { + public void upload(@Nonnull File file) throws IOException { try { upload(new FileInputStream(file)); } catch (IOUtil.ReadException ex) { @@ -93,11 +96,11 @@ public void upload(File file) throws IOException { } } - public void upload(InputStream in, long limit) throws IOException { + public void upload(@Nonnull InputStream in, long limit) throws IOException { upload(IOUtil.limit(in, limit)); } - public void upload(InputStream in) throws IOException { + public void upload(@Nonnull InputStream in) throws IOException { OutputStream out = getBody(); try { IOUtil.copyStreamToStream(in, out); @@ -106,7 +109,7 @@ public void upload(InputStream in) throws IOException { } } - public void upload(byte [] body) throws IOException { + public void upload(@Nonnull byte [] body) throws IOException { OutputStream out = getBody(); try { out.write(body); @@ -115,17 +118,17 @@ public void upload(byte [] body) throws IOException { } } - public void setProgressListener(IOUtil.ProgressListener progressListener) { + public void setProgressListener(@Nullable IOUtil.ProgressListener progressListener) { this.progressListener = progressListener; } } public static final class Response { private final int statusCode; - private final InputStream body; + private final @Nullable InputStream body; private final Map> headers; - public Response(int statusCode, InputStream body, Map> headers) { + public Response(int statusCode, @Nullable InputStream body, @Nonnull Map> headers) { this.statusCode = statusCode; this.body = body; this.headers = asUnmodifiableCaseInsensitiveMap(headers); @@ -147,7 +150,7 @@ public int getStatusCode() { * * @return HTTP response body */ - public InputStream getBody() { + public @Nullable InputStream getBody() { return body; } @@ -156,11 +159,12 @@ public InputStream getBody() { * * @return case-insensitive, unmodifiable headers */ - public Map> getHeaders() { + public @Nonnull Map> getHeaders() { return headers; } - private static final Map> asUnmodifiableCaseInsensitiveMap(Map> original) { + private static @Nonnull Map> asUnmodifiableCaseInsensitiveMap( + @Nonnull Map> original) { Map> insensitive = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for (Map.Entry> entry : original.entrySet()) { // Java HttpURLConnection puts status line as the 'null' key, e.g.: diff --git a/core/src/main/java/com/dropbox/core/http/OkHttp3Requestor.java b/core/src/main/java/com/dropbox/core/http/OkHttp3Requestor.java index 8978c45ba..803abd6c5 100644 --- a/core/src/main/java/com/dropbox/core/http/OkHttp3Requestor.java +++ b/core/src/main/java/com/dropbox/core/http/OkHttp3Requestor.java @@ -19,9 +19,11 @@ import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import okio.*; -/*>>> import checkers.nullness.quals.Nullable; */ /** * {@link HttpRequestor} implementation that uses OkHttp @@ -31,14 +33,14 @@ public class OkHttp3Requestor extends HttpRequestor { /** * Returns an {@code OkHttpClient} instance with the default settings for this SDK. */ - public static OkHttpClient defaultOkHttpClient() { + public static @Nonnull OkHttpClient defaultOkHttpClient() { return defaultOkHttpClientBuilder().build(); } /** * Returns an {@code OkHttpClient.Builder} instance with the default settings for this SDK. */ - public static OkHttpClient.Builder defaultOkHttpClientBuilder() { + public static @Nonnull OkHttpClient.Builder defaultOkHttpClientBuilder() { return new OkHttpClient.Builder() .connectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) .readTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) @@ -67,7 +69,7 @@ public static OkHttpClient.Builder defaultOkHttpClientBuilder() { * * */ - public OkHttp3Requestor(OkHttpClient client) { + public OkHttp3Requestor(@Nonnull OkHttpClient client) { if (client == null) throw new NullPointerException("client"); OkHttpUtil.assertNotSameThreadExecutor(client.dispatcher().executorService()); this.client = client; @@ -81,7 +83,7 @@ public OkHttp3Requestor(OkHttpClient client) { * * @return underlying {@code OkHttpClient} used by this requestor. */ - public OkHttpClient getClient() { + public @Nonnull OkHttpClient getClient() { return client; } @@ -93,7 +95,7 @@ public OkHttpClient getClient() { * * @param request Builder of request to be executed */ - protected void configureRequest(Request.Builder request) { } + protected void configureRequest(@Nonnull Request.Builder request) { } /** * Called before returning {@link Response} from a request. @@ -107,12 +109,12 @@ protected void configureRequest(Request.Builder request) { } * * @return OkHttp response */ - protected okhttp3.Response interceptResponse(okhttp3.Response response) { + protected @Nonnull okhttp3.Response interceptResponse(@Nonnull okhttp3.Response response) { return response; } @Override - public Response doGet(String url, Iterable
headers) throws IOException { + public @Nonnull Response doGet(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { Request.Builder builder = new Request.Builder().get().url(url); toOkHttpHeaders(headers, builder); configureRequest(builder); @@ -123,29 +125,33 @@ public Response doGet(String url, Iterable
headers) throws IOException { } @Override - public HttpRequestor.Uploader startPost(String url, Iterable
headers) throws IOException { + public @Nonnull HttpRequestor.Uploader startPost(@Nonnull String url, + @Nonnull Iterable
headers) throws IOException { return startUpload(url, headers, "POST"); } @Override - public HttpRequestor.Uploader startPut(String url, Iterable
headers) throws IOException { + public @Nonnull HttpRequestor.Uploader startPut(@Nonnull String url, + @Nonnull Iterable
headers) throws IOException { return startUpload(url, headers, "PUT"); } - private BufferedUploader startUpload(String url, Iterable
headers, String method) { + private @Nonnull BufferedUploader startUpload(@Nonnull String url, + @Nonnull Iterable
headers, + @Nonnull String method) { Request.Builder builder = new Request.Builder() .url(url); toOkHttpHeaders(headers, builder); return new BufferedUploader(method, builder); } - private static void toOkHttpHeaders(Iterable
headers, Request.Builder builder) { + private static void toOkHttpHeaders(@Nonnull Iterable
headers, @Nonnull Request.Builder builder) { for (Header header : headers) { builder.addHeader(header.getKey(), header.getValue()); } } - private static Map> fromOkHttpHeaders(Headers headers) { + private static @Nonnull Map> fromOkHttpHeaders(@Nonnull Headers headers) { Map> responseHeaders = new HashMap>(headers.size()); for (String name : headers.names()) { responseHeaders.put(name, headers.values(name)); @@ -174,7 +180,7 @@ private class BufferedUploader extends HttpRequestor.Uploader { private boolean closed; private boolean cancelled; - public BufferedUploader(String method, Request.Builder request) { + public BufferedUploader(@Nonnull String method, @Nonnull Request.Builder request) { this.method = method; this.request = request; @@ -193,7 +199,7 @@ private void assertNoBody() { } @Override - public OutputStream getBody() { + public @Nonnull OutputStream getBody() { // getBody() can be called multiple times to get access to the output stream. Don't // error if this is the case. if (body instanceof PipedRequestBody) { @@ -214,7 +220,7 @@ public OutputStream getBody() { } } - private void setBody(RequestBody body) { + private void setBody(@Nonnull RequestBody body) { assertNoBody(); this.body = body; this.request.method(method, body); @@ -222,12 +228,12 @@ private void setBody(RequestBody body) { } @Override - public void upload(File file) { + public void upload(@Nonnull File file) { setBody(RequestBody.Companion.create(file, null)); } @Override - public void upload(byte [] body) { + public void upload(@Nonnull byte [] body) { setBody(RequestBody.Companion.create(body, null)); } @@ -253,7 +259,7 @@ public void abort() { } @Override - public Response finish() throws IOException { + public @Nonnull Response finish() throws IOException { if (cancelled) { throw new IllegalStateException("Already aborted"); } @@ -280,17 +286,17 @@ public Response finish() throws IOException { } public static final class AsyncCallback implements Callback { - private PipedRequestBody body; - private IOException error; - private okhttp3.Response response; + private @Nonnull PipedRequestBody body; + private @Nullable IOException error; + private @Nullable okhttp3.Response response; - private AsyncCallback(PipedRequestBody body) { + private AsyncCallback(@Nonnull PipedRequestBody body) { this.body = body; this.error = null; this.response = null; } - public synchronized okhttp3.Response getResponse() throws IOException { + public synchronized @Nonnull okhttp3.Response getResponse() throws IOException { while (error == null && response == null) { try { wait(); @@ -306,14 +312,14 @@ public synchronized okhttp3.Response getResponse() throws IOException { } @Override - public synchronized void onFailure(Call call, IOException ex) { + public synchronized void onFailure(@Nonnull Call call, @Nonnull IOException ex) { this.error = ex; this.body.close(); notifyAll(); } @Override - public synchronized void onResponse(Call call, okhttp3.Response response) throws IOException { + public synchronized void onResponse(@Nonnull Call call, @Nonnull okhttp3.Response response) throws IOException { this.response = response; notifyAll(); } @@ -322,15 +328,15 @@ public synchronized void onResponse(Call call, okhttp3.Response response) throws private static class PipedRequestBody extends RequestBody implements Closeable { private final OkHttpUtil.PipedStream stream; - private IOUtil.ProgressListener listener; + private @Nullable IOUtil.ProgressListener listener; public PipedRequestBody() { this.stream = new OkHttpUtil.PipedStream(); } - public void setListener(IOUtil.ProgressListener listener) { this.listener = listener; } + public void setListener(@Nullable IOUtil.ProgressListener listener) { this.listener = listener; } - public OutputStream getOutputStream() { + public @Nonnull OutputStream getOutputStream() { return stream.getOutputStream(); } @@ -345,7 +351,7 @@ public void close() { } @Override - public MediaType contentType() { + public @Nullable MediaType contentType() { return null; } @@ -355,7 +361,7 @@ public long contentLength() { } @Override - public void writeTo(BufferedSink sink) throws IOException { + public void writeTo(@Nonnull BufferedSink sink) throws IOException { CountingSink countingSink = new CountingSink(sink); BufferedSink bufferedSink = Okio.buffer(countingSink); stream.writeTo(bufferedSink); @@ -366,12 +372,12 @@ public void writeTo(BufferedSink sink) throws IOException { private final class CountingSink extends ForwardingSink { private long bytesWritten = 0; - public CountingSink(Sink delegate) { + public CountingSink(@Nonnull Sink delegate) { super(delegate); } @Override - public void write(Buffer source, long byteCount) throws IOException { + public void write(@Nonnull Buffer source, long byteCount) throws IOException { super.write(source, byteCount); bytesWritten += byteCount; diff --git a/core/src/main/java/com/dropbox/core/http/OkHttpRequestor.java b/core/src/main/java/com/dropbox/core/http/OkHttpRequestor.java index 9de7e5eee..ece414ccb 100644 --- a/core/src/main/java/com/dropbox/core/http/OkHttpRequestor.java +++ b/core/src/main/java/com/dropbox/core/http/OkHttpRequestor.java @@ -19,9 +19,11 @@ import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import okio.*; -/*>>> import checkers.nullness.quals.Nullable; */ /** * {@link HttpRequestor} implementation that uses OkHttp @@ -35,7 +37,7 @@ public class OkHttpRequestor extends HttpRequestor { /** * Returns an {@code OkHttpClient} instance with the default settings for this SDK. */ - public static OkHttpClient defaultOkHttpClient() { + public static @Nonnull OkHttpClient defaultOkHttpClient() { OkHttpClient client = new OkHttpClient(); client.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); client.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); @@ -60,7 +62,7 @@ public static OkHttpClient defaultOkHttpClient() { * * */ - public OkHttpRequestor(OkHttpClient client) { + public OkHttpRequestor(@Nonnull OkHttpClient client) { if (client == null) throw new NullPointerException("client"); OkHttpUtil.assertNotSameThreadExecutor(client.getDispatcher().getExecutorService()); this.client = client.clone(); @@ -74,7 +76,7 @@ public OkHttpRequestor(OkHttpClient client) { * * @return clone of the underlying {@code OkHttpClient} used by this requestor. */ - public OkHttpClient getClient() { + public @Nonnull OkHttpClient getClient() { return client; } @@ -86,7 +88,7 @@ public OkHttpClient getClient() { * * @param request Builder of request to be executed */ - protected void configureRequest(Request.Builder request) { } + protected void configureRequest(@Nonnull Request.Builder request) { } /** * Called before returning {@link Response} from a request. @@ -100,12 +102,12 @@ protected void configureRequest(Request.Builder request) { } * * @return OkHttp response */ - protected com.squareup.okhttp.Response interceptResponse(com.squareup.okhttp.Response response) { + protected @Nonnull com.squareup.okhttp.Response interceptResponse(@Nonnull com.squareup.okhttp.Response response) { return response; } @Override - public Response doGet(String url, Iterable
headers) throws IOException { + public @Nonnull Response doGet(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { Request.Builder builder = new Request.Builder().get().url(url); toOkHttpHeaders(headers, builder); configureRequest(builder); @@ -116,29 +118,33 @@ public Response doGet(String url, Iterable
headers) throws IOException { } @Override - public HttpRequestor.Uploader startPost(String url, Iterable
headers) throws IOException { + public @Nonnull HttpRequestor.Uploader startPost(@Nonnull String url, + @Nonnull Iterable
headers) throws IOException { return startUpload(url, headers, "POST"); } @Override - public HttpRequestor.Uploader startPut(String url, Iterable
headers) throws IOException { + public @Nonnull HttpRequestor.Uploader startPut(@Nonnull String url, + @Nonnull Iterable
headers) throws IOException { return startUpload(url, headers, "PUT"); } - private BufferedUploader startUpload(String url, Iterable
headers, String method) { + private @Nonnull BufferedUploader startUpload(@Nonnull String url, + @Nonnull Iterable
headers, + @Nonnull String method) { Request.Builder builder = new Request.Builder() .url(url); toOkHttpHeaders(headers, builder); return new BufferedUploader(method, builder); } - private static void toOkHttpHeaders(Iterable
headers, Request.Builder builder) { + private static void toOkHttpHeaders(@Nonnull Iterable
headers, @Nonnull Request.Builder builder) { for (Header header : headers) { builder.addHeader(header.getKey(), header.getValue()); } } - private static Map> fromOkHttpHeaders(Headers headers) { + private static @Nonnull Map> fromOkHttpHeaders(@Nonnull Headers headers) { Map> responseHeaders = new HashMap>(headers.size()); for (String name : headers.names()) { responseHeaders.put(name, headers.values(name)); @@ -167,7 +173,7 @@ private class BufferedUploader extends HttpRequestor.Uploader { private boolean closed; private boolean cancelled; - public BufferedUploader(String method, Request.Builder request) { + public BufferedUploader(@Nonnull String method, @Nonnull Request.Builder request) { this.method = method; this.request = request; @@ -186,7 +192,7 @@ private void assertNoBody() { } @Override - public OutputStream getBody() { + public @Nonnull OutputStream getBody() { // getBody() can be called multiple times to get access to the output stream. Don't // error if this is the case. if (body instanceof PipedRequestBody) { @@ -206,7 +212,7 @@ public OutputStream getBody() { } } - private void setBody(RequestBody body) { + private void setBody(@Nonnull RequestBody body) { assertNoBody(); this.body = body; this.request.method(method, body); @@ -214,12 +220,12 @@ private void setBody(RequestBody body) { } @Override - public void upload(File file) { + public void upload(@Nonnull File file) { setBody(RequestBody.create(null, file)); } @Override - public void upload(byte [] body) { + public void upload(@Nonnull byte [] body) { setBody(RequestBody.create(null, body)); } @@ -245,7 +251,7 @@ public void abort() { } @Override - public Response finish() throws IOException { + public @Nonnull Response finish() throws IOException { if (cancelled) { throw new IllegalStateException("Already aborted"); } @@ -272,15 +278,15 @@ public Response finish() throws IOException { } public static final class AsyncCallback implements Callback { - private IOException error; - private com.squareup.okhttp.Response response; + private @Nullable IOException error; + private @Nullable com.squareup.okhttp.Response response; private AsyncCallback() { this.error = null; this.response = null; } - public synchronized com.squareup.okhttp.Response getResponse() throws IOException { + public synchronized @Nonnull com.squareup.okhttp.Response getResponse() throws IOException { while (error == null && response == null) { try { wait(); @@ -296,13 +302,13 @@ public synchronized com.squareup.okhttp.Response getResponse() throws IOExceptio } @Override - public synchronized void onFailure(Request request, IOException ex) { + public synchronized void onFailure(@Nonnull Request request, @Nonnull IOException ex) { this.error = ex; notifyAll(); } @Override - public synchronized void onResponse(com.squareup.okhttp.Response response) throws IOException { + public synchronized void onResponse(@Nonnull com.squareup.okhttp.Response response) throws IOException { this.response = response; notifyAll(); } @@ -311,15 +317,15 @@ public synchronized void onResponse(com.squareup.okhttp.Response response) throw private static class PipedRequestBody extends RequestBody implements Closeable { private final OkHttpUtil.PipedStream stream; - private IOUtil.ProgressListener listener; + private @Nullable IOUtil.ProgressListener listener; public PipedRequestBody() { this.stream = new OkHttpUtil.PipedStream(); } - public void setListener(IOUtil.ProgressListener listener) { this.listener = listener; } + public void setListener(@Nullable IOUtil.ProgressListener listener) { this.listener = listener; } - public OutputStream getOutputStream() { + public @Nonnull OutputStream getOutputStream() { return stream.getOutputStream(); } @@ -329,7 +335,7 @@ public void close() { } @Override - public MediaType contentType() { + public @Nullable MediaType contentType() { return null; } @@ -339,7 +345,7 @@ public long contentLength() { } @Override - public void writeTo(BufferedSink sink) throws IOException { + public void writeTo(@Nonnull BufferedSink sink) throws IOException { CountingSink countingSink = new CountingSink(sink); BufferedSink bufferedSink = Okio.buffer(countingSink); stream.writeTo(bufferedSink); @@ -350,12 +356,12 @@ public void writeTo(BufferedSink sink) throws IOException { private final class CountingSink extends ForwardingSink { private long bytesWritten = 0; - public CountingSink(Sink delegate) { + public CountingSink(@Nonnull Sink delegate) { super(delegate); } @Override - public void write(Buffer source, long byteCount) throws IOException { + public void write(@Nonnull Buffer source, long byteCount) throws IOException { super.write(source, byteCount); bytesWritten += byteCount; diff --git a/core/src/main/java/com/dropbox/core/http/OkHttpUtil.java b/core/src/main/java/com/dropbox/core/http/OkHttpUtil.java index a40d9024a..03c753472 100644 --- a/core/src/main/java/com/dropbox/core/http/OkHttpUtil.java +++ b/core/src/main/java/com/dropbox/core/http/OkHttpUtil.java @@ -9,20 +9,22 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; + import okio.BufferedSink; import okio.Okio; final class OkHttpUtil { - public static void assertNotSameThreadExecutor(ExecutorService executor) { + public static void assertNotSameThreadExecutor(@Nonnull ExecutorService executor) { Thread current = Thread.currentThread(); Thread executed; try { executed = executor.submit(new Callable() { @Override - public Thread call() { + public @Nonnull Thread call() { return Thread.currentThread(); } }).get(2, TimeUnit.MINUTES); @@ -57,7 +59,7 @@ public PipedStream() { } } - public OutputStream getOutputStream() { + public @Nonnull OutputStream getOutputStream() { return out; } @@ -75,7 +77,7 @@ public void close() { } } - public void writeTo(BufferedSink sink) throws IOException { + public void writeTo(@Nonnull BufferedSink sink) throws IOException { sink.writeAll(Okio.source(in)); } } diff --git a/core/src/main/java/com/dropbox/core/http/StandardHttpRequestor.java b/core/src/main/java/com/dropbox/core/http/StandardHttpRequestor.java index 51d4878c7..5a5446861 100644 --- a/core/src/main/java/com/dropbox/core/http/StandardHttpRequestor.java +++ b/core/src/main/java/com/dropbox/core/http/StandardHttpRequestor.java @@ -9,6 +9,7 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Logger; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSocketFactory; @@ -16,7 +17,6 @@ import com.dropbox.core.util.IOUtil; import com.dropbox.core.util.ProgressOutputStream; -/*>>> import checkers.nullness.quals.Nullable; */ /** * {@link HttpRequestor} implementation that uses Java's standard library @@ -35,7 +35,7 @@ public class StandardHttpRequestor extends HttpRequestor { * A thread-safe instance of {@code StandardHttpRequestor} that connects directly * (as opposed to using a proxy). */ - public static final StandardHttpRequestor INSTANCE = new StandardHttpRequestor(Config.DEFAULT_INSTANCE); + public static final @Nonnull StandardHttpRequestor INSTANCE = new StandardHttpRequestor(Config.DEFAULT_INSTANCE); private static volatile boolean certPinningWarningLogged = false; @@ -44,11 +44,11 @@ public class StandardHttpRequestor extends HttpRequestor { /** * Creates an instance that connects through the given proxy. */ - public StandardHttpRequestor(Config config) { + public StandardHttpRequestor(@Nonnull Config config) { this.config = config; } - private Response toResponse(HttpURLConnection conn) throws IOException { + private @Nonnull Response toResponse(@Nonnull HttpURLConnection conn) throws IOException { int responseCode = conn.getResponseCode(); InputStream bodyStream; if (responseCode >= 400 || responseCode == -1) { @@ -61,7 +61,7 @@ private Response toResponse(HttpURLConnection conn) throws IOException { } @Override - public Response doGet(String url, Iterable
headers) throws IOException { + public @Nonnull Response doGet(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { HttpURLConnection conn = prepRequest(url, headers, false); conn.setRequestMethod("GET"); conn.connect(); @@ -69,14 +69,14 @@ public Response doGet(String url, Iterable
headers) throws IOException { } @Override - public Uploader startPost(String url, Iterable
headers) throws IOException { + public @Nonnull Uploader startPost(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { HttpURLConnection conn = prepRequest(url, headers, false); conn.setRequestMethod("POST"); return new Uploader(conn); } @Override - public Uploader startPostInStreamingMode(String url, Iterable
headers) throws + public @Nonnull Uploader startPostInStreamingMode(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { HttpURLConnection conn = prepRequest(url, headers, true); conn.setRequestMethod("POST"); @@ -84,7 +84,7 @@ public Uploader startPostInStreamingMode(String url, Iterable
headers) t } @Override - public Uploader startPut(String url, Iterable
headers) throws IOException { + public @Nonnull Uploader startPut(@Nonnull String url, @Nonnull Iterable
headers) throws IOException { HttpURLConnection conn = prepRequest(url, headers, false); conn.setRequestMethod("PUT"); return new Uploader(conn); @@ -98,7 +98,7 @@ public Uploader startPut(String url, Iterable
headers) throws IOExceptio * @deprecated use {@link #configure} instead. */ @Deprecated - protected void configureConnection(HttpsURLConnection conn) throws IOException { } + protected void configureConnection(@Nonnull HttpsURLConnection conn) throws IOException { } /** * Can be overriden to configure the underlying {@link HttpURLConnection} used to make network @@ -113,7 +113,7 @@ protected void configureConnection(HttpsURLConnection conn) throws IOException { * * @param conn URL connection object returned after creating an https network request. */ - protected void configure(HttpURLConnection conn) throws IOException { } + protected void configure(@Nonnull HttpURLConnection conn) throws IOException { } /** * Called before returning {@link Response} from a request. @@ -127,9 +127,9 @@ protected void configure(HttpURLConnection conn) throws IOException { } * * @param conn HTTP URL connection */ - protected void interceptResponse(HttpURLConnection conn) throws IOException { } + protected void interceptResponse(@Nonnull HttpURLConnection conn) throws IOException { } - private static OutputStream getOutputStream(HttpURLConnection conn) throws IOException { + private static @Nonnull OutputStream getOutputStream(@Nonnull HttpURLConnection conn) throws IOException { conn.setDoOutput(true); return conn.getOutputStream(); } @@ -138,7 +138,7 @@ private class Uploader extends HttpRequestor.Uploader { private final ProgressOutputStream out; private HttpURLConnection conn; - public Uploader(HttpURLConnection conn) throws IOException { + public Uploader(@Nonnull HttpURLConnection conn) throws IOException { this.conn = conn; this.out = new ProgressOutputStream(getOutputStream(conn)); @@ -146,7 +146,7 @@ public Uploader(HttpURLConnection conn) throws IOException { } @Override - public OutputStream getBody() { + public @Nonnull OutputStream getBody() { return out; } @@ -179,7 +179,7 @@ public void close() { } @Override - public Response finish() throws IOException { + public @Nonnull Response finish() throws IOException { if (conn == null) { throw new IllegalStateException("Can't finish(). Uploader already closed."); } @@ -191,13 +191,16 @@ public Response finish() throws IOException { } } - public void setProgressListener(IOUtil.ProgressListener progressListener) { + @Override + public void setProgressListener(@Nullable IOUtil.ProgressListener progressListener) { out.setListener(progressListener); } } - protected HttpURLConnection prepRequest(String url, Iterable
headers, boolean streaming) throws IOException { + protected @Nonnull HttpURLConnection prepRequest(@Nonnull String url, + @Nonnull Iterable
headers, + boolean streaming) throws IOException { URL urlObject = new URL(url); HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection(config.getProxy()); @@ -262,17 +265,17 @@ public static final class Config { * {@link Config} with all its attributes set to their default * values. */ - public static final Config DEFAULT_INSTANCE = builder().build(); + public static final @Nonnull Config DEFAULT_INSTANCE = builder().build(); private final Proxy proxy; private final long connectTimeoutMillis; private final long readTimeoutMillis; private final SSLSocketFactory sslSocketFactory; - private Config(Proxy proxy, + private Config(@Nonnull Proxy proxy, long connectTimeoutMillis, long readTimeoutMillis, - SSLSocketFactory sslSocketFactory) { + @Nullable SSLSocketFactory sslSocketFactory) { this.proxy = proxy; this.connectTimeoutMillis = connectTimeoutMillis; this.readTimeoutMillis = readTimeoutMillis; @@ -284,7 +287,7 @@ private Config(Proxy proxy, * * @return proxy configuration to use for network connections. */ - public Proxy getProxy() { + public @Nonnull Proxy getProxy() { return proxy; } @@ -320,8 +323,7 @@ public long getReadTimeoutMillis() { * * @return SSLSocketFactory or null. */ - @Nullable - public SSLSocketFactory getSslSocketFactory() { + public @Nullable SSLSocketFactory getSslSocketFactory() { return sslSocketFactory; } @@ -332,7 +334,7 @@ public SSLSocketFactory getSslSocketFactory() { * * @return builder for creating a copy of this config. */ - public Builder copy() { + public @Nonnull Builder copy() { return new Builder(proxy, connectTimeoutMillis, readTimeoutMillis, sslSocketFactory); } @@ -341,7 +343,7 @@ public Builder copy() { * * @return builder for creating an instance of this class */ - public static Builder builder() { + public static @Nonnull Builder builder() { return new Builder(); } @@ -358,7 +360,10 @@ private Builder() { this(Proxy.NO_PROXY, DEFAULT_CONNECT_TIMEOUT_MILLIS, DEFAULT_READ_TIMEOUT_MILLIS, null); } - private Builder(Proxy proxy, long connectTimeoutMillis, long readTimeoutMillis, SSLSocketFactory sslSocketFactory) { + private Builder(@Nonnull Proxy proxy, + long connectTimeoutMillis, + long readTimeoutMillis, + @Nullable SSLSocketFactory sslSocketFactory) { this.proxy = proxy; this.connectTimeoutMillis = connectTimeoutMillis; this.readTimeoutMillis = readTimeoutMillis; @@ -374,7 +379,7 @@ private Builder(Proxy proxy, long connectTimeoutMillis, long readTimeoutMillis, * * @throws NullPointerException if {@code proxy} is {@code null} */ - public Builder withProxy(Proxy proxy) { + public @Nonnull Builder withProxy(@Nonnull Proxy proxy) { if (proxy == null) { throw new NullPointerException("proxy"); } @@ -388,7 +393,7 @@ public Builder withProxy(Proxy proxy) { * * @return this builder */ - public Builder withNoConnectTimeout() { + public @Nonnull Builder withNoConnectTimeout() { return withConnectTimeout(0L, TimeUnit.MILLISECONDS); } @@ -405,7 +410,7 @@ public Builder withNoConnectTimeout() { * @throws IllegalArgumentException if {@code timeout} is negative * @throws NullPointerException if {@code unit} is {@code null} */ - public Builder withConnectTimeout(long timeout, TimeUnit unit) { + public @Nonnull Builder withConnectTimeout(long timeout, @Nonnull TimeUnit unit) { this.connectTimeoutMillis = checkTimeoutMillis(timeout, unit); return this; } @@ -415,7 +420,7 @@ public Builder withConnectTimeout(long timeout, TimeUnit unit) { * * @return this builder */ - public Builder withNoReadTimeout() { + public @Nonnull Builder withNoReadTimeout() { return withReadTimeout(0L, TimeUnit.MILLISECONDS); } @@ -437,7 +442,7 @@ public Builder withNoReadTimeout() { * @throws IllegalArgumentException if {@code timeout} is negative * @throws NullPointerException if {@code unit} is {@code null} */ - public Builder withReadTimeout(long timeout, TimeUnit unit) { + public @Nonnull Builder withReadTimeout(long timeout, @Nonnull TimeUnit unit) { this.readTimeoutMillis = checkTimeoutMillis(timeout, unit); return this; } @@ -452,7 +457,7 @@ public Builder withReadTimeout(long timeout, TimeUnit unit) { * * @return this builder */ - public Builder withSslSocketFactory(SSLSocketFactory sslSocketFactory) { + public @Nonnull Builder withSslSocketFactory(@Nullable SSLSocketFactory sslSocketFactory) { this.sslSocketFactory = sslSocketFactory; return this; } @@ -462,7 +467,7 @@ public Builder withSslSocketFactory(SSLSocketFactory sslSocketFactory) { * * @return {@link Config} with this builder's values */ - public Config build() { + public @Nonnull Config build() { return new Config( proxy, connectTimeoutMillis, @@ -471,7 +476,7 @@ public Config build() { ); } - private static long checkTimeoutMillis(long timeout, TimeUnit unit) { + private static long checkTimeoutMillis(long timeout, @Nonnull TimeUnit unit) { if (unit == null) { throw new NullPointerException("unit"); } diff --git a/core/src/main/java/com/dropbox/core/json/JsonArrayReader.java b/core/src/main/java/com/dropbox/core/json/JsonArrayReader.java index 39c7cb292..5f7b40c89 100644 --- a/core/src/main/java/com/dropbox/core/json/JsonArrayReader.java +++ b/core/src/main/java/com/dropbox/core/json/JsonArrayReader.java @@ -3,37 +3,38 @@ import com.dropbox.core.util.Collector; import com.fasterxml.jackson.core.*; +import javax.annotation.Nonnull; import java.io.IOException; import java.util.List; public class JsonArrayReader extends JsonReader { - public final JsonReader elementReader; - public final Collector collector; + public final @Nonnull JsonReader elementReader; + public final @Nonnull Collector collector; - public JsonArrayReader(JsonReader elementReader, Collector collector) + public JsonArrayReader(@Nonnull JsonReader elementReader, @Nonnull Collector collector) { this.elementReader = elementReader; this.collector = collector; } - public static JsonArrayReader> mk(JsonReader elementReader) + public static @Nonnull JsonArrayReader> mk(@Nonnull JsonReader elementReader) { return new JsonArrayReader>(elementReader, new Collector.ArrayListCollector()); } - public static JsonArrayReader mk(JsonReader elementReader, Collector collector) + public static @Nonnull JsonArrayReader mk(@Nonnull JsonReader elementReader, @Nonnull Collector collector) { return new JsonArrayReader(elementReader, collector); } - public L read(JsonParser parser) + public @Nonnull L read(@Nonnull JsonParser parser) throws JsonReadException, IOException { return read(elementReader, collector, parser); } - public static L read(JsonReader elementReader, Collector collector, JsonParser parser) + public static @Nonnull L read(@Nonnull JsonReader elementReader, @Nonnull Collector collector, @Nonnull JsonParser parser) throws JsonReadException, IOException { expectArrayStart(parser); diff --git a/core/src/main/java/com/dropbox/core/json/JsonDateReader.java b/core/src/main/java/com/dropbox/core/json/JsonDateReader.java index 3261ac402..2936c3e48 100644 --- a/core/src/main/java/com/dropbox/core/json/JsonDateReader.java +++ b/core/src/main/java/com/dropbox/core/json/JsonDateReader.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; +import javax.annotation.Nonnull; import java.io.IOException; import java.util.Date; import java.util.GregorianCalendar; @@ -16,9 +17,9 @@ public class JsonDateReader /** * A parser for dates returned by the Dropbox API. */ - public static final JsonReader Dropbox = new JsonReader() { + public static final @Nonnull JsonReader Dropbox = new JsonReader() { @Override - public Date read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull Date read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation l = parser.getCurrentLocation(); try { @@ -38,7 +39,7 @@ public Date read(JsonParser parser) throws IOException, JsonReadException } }; - public static Date parseDropboxDate(char[] buffer, int offset, int length) + public static @Nonnull Date parseDropboxDate(@Nonnull char[] buffer, int offset, int length) throws java.text.ParseException { int i = offset; @@ -147,7 +148,7 @@ public static Date parseDropboxDate(char[] buffer, int offset, int length) return c.getTime(); } - public static final TimeZone UTC = TimeZone.getTimeZone("UTC"); + public static final @Nonnull TimeZone UTC = TimeZone.getTimeZone("UTC"); private static boolean isDigit(char c) { @@ -229,9 +230,9 @@ public static int getMonthIndex(char a, char b, char c) * (e.g. {@literal "2010-01-01T12:00:00Z"} * or {@literal "2010-01-01T12:00:00.000Z"}). */ - public static final JsonReader DropboxV2 = new JsonReader() { + public static final @Nonnull JsonReader DropboxV2 = new JsonReader() { @Override - public Date read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull Date read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation l = parser.getCurrentLocation(); try { @@ -251,7 +252,7 @@ public Date read(JsonParser parser) throws IOException, JsonReadException } }; - public static Date parseDropbox8601Date(char[] buffer, int offset, int length) + public static @Nonnull Date parseDropbox8601Date(@Nonnull char[] buffer, int offset, int length) throws java.text.ParseException { int i = offset; diff --git a/core/src/main/java/com/dropbox/core/json/JsonReadException.java b/core/src/main/java/com/dropbox/core/json/JsonReadException.java index 2bbc572ef..39e77c679 100644 --- a/core/src/main/java/com/dropbox/core/json/JsonReadException.java +++ b/core/src/main/java/com/dropbox/core/json/JsonReadException.java @@ -1,28 +1,29 @@ package com.dropbox.core.json; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonProcessingException; import java.io.File; -/*>>> import checkers.nullness.quals.Nullable; */ public final class JsonReadException extends java.lang.Exception { public static final long serialVersionUID = 0; - public final String error; - public final JsonLocation location; - private /*@Nullable*/PathPart path; + public final @Nonnull String error; + public final @Nonnull JsonLocation location; + private @Nullable PathPart path; - public JsonReadException(String error, JsonLocation location) + public JsonReadException(@Nonnull String error, @Nonnull JsonLocation location) { this.error = error; this.location = location; this.path = null; } - public JsonReadException(String error, JsonLocation location, Throwable cause) + public JsonReadException(@Nonnull String error, @Nonnull JsonLocation location, @Nonnull Throwable cause) { super(cause); this.error = error; @@ -30,19 +31,19 @@ public JsonReadException(String error, JsonLocation location, Throwable cause) this.path = null; } - public JsonReadException addFieldContext(String fieldName) + public @Nonnull JsonReadException addFieldContext(@Nonnull String fieldName) { this.path = new PathPart('"' + fieldName + '"', this.path); return this; } - public JsonReadException addArrayContext(int index) + public @Nonnull JsonReadException addArrayContext(int index) { this.path = new PathPart(Integer.toString(index), this.path); return this; } - public String getMessage() + public @Nonnull String getMessage() { StringBuilder buf = new StringBuilder(); @@ -68,7 +69,7 @@ public String getMessage() return buf.toString(); } - public static void toStringLocation(StringBuilder buf, JsonLocation location) + public static void toStringLocation(@Nonnull StringBuilder buf, @Nonnull JsonLocation location) { Object sourceRef = location.getSourceRef(); if (sourceRef instanceof File) { @@ -84,17 +85,17 @@ public static void toStringLocation(StringBuilder buf, JsonLocation location) public static final class PathPart { - public final String description; - public final /*@Nullable*/PathPart next; + public final @Nonnull String description; + public final @Nullable PathPart next; - public PathPart(String description, /*@Nullable*/PathPart next) + public PathPart(@Nonnull String description, @Nullable PathPart next) { this.description = description; this.next = next; } } - public static JsonReadException fromJackson(JsonProcessingException ex) + public static @Nonnull JsonReadException fromJackson(@Nonnull JsonProcessingException ex) { String message = ex.getMessage(); diff --git a/core/src/main/java/com/dropbox/core/json/JsonReader.java b/core/src/main/java/com/dropbox/core/json/JsonReader.java index ffb037335..a4072d996 100644 --- a/core/src/main/java/com/dropbox/core/json/JsonReader.java +++ b/core/src/main/java/com/dropbox/core/json/JsonReader.java @@ -1,5 +1,7 @@ package com.dropbox.core.json; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.util.IOUtil; import static com.dropbox.core.util.LangUtil.mkAssert; @@ -17,38 +19,37 @@ import java.util.HashMap; -/*>>> import checkers.nullness.quals.Nullable; */ public abstract class JsonReader { - public abstract T read(JsonParser parser) + public abstract @Nullable T read(@Nonnull JsonParser parser) throws IOException, JsonReadException; - public T readFromTags(String[] tags, JsonParser parser) + public @Nullable T readFromTags(@Nonnull String[] tags, @Nonnull JsonParser parser) throws IOException, JsonReadException { return null; // Must override for struct } - public T readFields(JsonParser parser) + public @Nullable T readFields(@Nonnull JsonParser parser) throws IOException, JsonReadException { return null; // Must override for struct } - public void validate(T value) + public void validate(@Nullable T value) { // Base implementation does nothing. } - public final T readField(JsonParser parser, String fieldName, /*@Nullable*/Object v) + public final @Nullable T readField(@Nonnull JsonParser parser, @Nonnull String fieldName, @Nullable Object v) throws IOException, JsonReadException { if (v != null) throw new JsonReadException("duplicate field \"" + fieldName + "\"", parser.getTokenLocation()); return read(parser); } - public final /*@Nullable*/T readOptional(JsonParser parser) + public final @Nullable T readOptional(@Nonnull JsonParser parser) throws IOException, JsonReadException { if (parser.getCurrentToken() == JsonToken.VALUE_NULL) { @@ -65,7 +66,7 @@ public final T readField(JsonParser parser, String fieldName, /*@Nullable*/Objec * Returns null if there isn't a ".tag" field; otherwise an array of strings (the tags). * Initially the parser must be positioned right after the opening brace. */ - public static String[] readTags(JsonParser parser) + public static @Nullable String[] readTags(@Nonnull JsonParser parser) throws IOException, JsonReadException { if (parser.getCurrentToken() != JsonToken.FIELD_NAME) { @@ -92,7 +93,7 @@ public static String[] readTags(JsonParser parser) * logical location information (see {@link JsonReadException#addFieldContext} and * {@link JsonReadException#addArrayContext}). */ - public static JsonToken nextToken(JsonParser parser) + public static @Nullable JsonToken nextToken(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { @@ -106,7 +107,7 @@ public static JsonToken nextToken(JsonParser parser) // ------------------------------------------------------------------ // Delimiter checking helpers. - public static JsonLocation expectObjectStart(JsonParser parser) + public static @Nonnull JsonLocation expectObjectStart(@Nonnull JsonParser parser) throws IOException, JsonReadException { if (parser.getCurrentToken() != JsonToken.START_OBJECT) { @@ -117,7 +118,7 @@ public static JsonLocation expectObjectStart(JsonParser parser) return loc; } - public static void expectObjectEnd(JsonParser parser) + public static void expectObjectEnd(@Nonnull JsonParser parser) throws IOException, JsonReadException { if (parser.getCurrentToken() != JsonToken.END_OBJECT) { @@ -126,7 +127,7 @@ public static void expectObjectEnd(JsonParser parser) nextToken(parser); } - public static JsonLocation expectArrayStart(JsonParser parser) + public static @Nonnull JsonLocation expectArrayStart(@Nonnull JsonParser parser) throws IOException, JsonReadException { if (parser.getCurrentToken() != JsonToken.START_ARRAY) { @@ -137,7 +138,7 @@ public static JsonLocation expectArrayStart(JsonParser parser) return loc; } - public static JsonLocation expectArrayEnd(JsonParser parser) + public static @Nonnull JsonLocation expectArrayEnd(@Nonnull JsonParser parser) throws IOException, JsonReadException { if (parser.getCurrentToken() != JsonToken.END_ARRAY) { @@ -148,17 +149,17 @@ public static JsonLocation expectArrayEnd(JsonParser parser) return loc; } - public static boolean isArrayEnd(JsonParser parser) + public static boolean isArrayEnd(@Nonnull JsonParser parser) { return (parser.getCurrentToken() == JsonToken.END_ARRAY); } - public static boolean isArrayStart(JsonParser parser) + public static boolean isArrayStart(@Nonnull JsonParser parser) { return (parser.getCurrentToken() == JsonToken.START_ARRAY); } - public static void skipValue(JsonParser parser) + public static void skipValue(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { @@ -173,16 +174,16 @@ public static void skipValue(JsonParser parser) // ------------------------------------------------------------------ // Helpers for various types. - public static final JsonReader UnsignedLongReader = new JsonReader() { + public static final @Nonnull JsonReader UnsignedLongReader = new JsonReader() { @Override - public Long read(JsonParser parser) + public @Nonnull Long read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return readUnsignedLong(parser); } }; - public static long readUnsignedLong(JsonParser parser) + public static long readUnsignedLong(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { @@ -198,16 +199,16 @@ public static long readUnsignedLong(JsonParser parser) } } - public static long readUnsignedLongField(JsonParser parser, String fieldName, long v) + public static long readUnsignedLongField(@Nonnull JsonParser parser, @Nonnull String fieldName, long v) throws IOException, JsonReadException { if (v >= 0) throw new JsonReadException("duplicate field \"" + fieldName + "\"", parser.getCurrentLocation()); return JsonReader.readUnsignedLong(parser); } - public static final JsonReader Int64Reader = new JsonReader() + public static final @Nonnull JsonReader Int64Reader = new JsonReader() { - public Long read(JsonParser parser) + public @Nonnull Long read(@Nonnull JsonParser parser) throws IOException, JsonReadException { long v = parser.getLongValue(); @@ -216,9 +217,9 @@ public Long read(JsonParser parser) } }; - public static final JsonReader Int32Reader = new JsonReader() + public static final @Nonnull JsonReader Int32Reader = new JsonReader() { - public Integer read(JsonParser parser) + public @Nonnull Integer read(@Nonnull JsonParser parser) throws IOException, JsonReadException { int v = parser.getIntValue(); @@ -228,9 +229,9 @@ public Integer read(JsonParser parser) }; // NOTE: This can't read values >= 2**63. - public static final JsonReader UInt64Reader = new JsonReader() + public static final @Nonnull JsonReader UInt64Reader = new JsonReader() { - public Long read(JsonParser parser) + public @Nonnull Long read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return readUnsignedLong(parser); @@ -238,9 +239,9 @@ public Long read(JsonParser parser) }; // NOTE: This stores the value in a Long. - public static final JsonReader UInt32Reader = new JsonReader() + public static final @Nonnull JsonReader UInt32Reader = new JsonReader() { - public Long read(JsonParser parser) + public @Nonnull Long read(@Nonnull JsonParser parser) throws IOException, JsonReadException { long v = readUnsignedLong(parser); @@ -251,9 +252,9 @@ public Long read(JsonParser parser) } }; - public static final JsonReader Float64Reader = new JsonReader() + public static final @Nonnull JsonReader Float64Reader = new JsonReader() { - public Double read(JsonParser parser) + public @Nonnull Double read(@Nonnull JsonParser parser) throws IOException, JsonReadException { double v = parser.getDoubleValue(); @@ -262,9 +263,9 @@ public Double read(JsonParser parser) } }; - public static final JsonReader Float32Reader = new JsonReader() + public static final @Nonnull JsonReader Float32Reader = new JsonReader() { - public Float read(JsonParser parser) + public @Nonnull Float read(@Nonnull JsonParser parser) throws IOException, JsonReadException { float v = parser.getFloatValue(); @@ -273,9 +274,9 @@ public Float read(JsonParser parser) } }; - public static final JsonReader StringReader = new JsonReader() + public static final @Nonnull JsonReader StringReader = new JsonReader() { - public String read(JsonParser parser) + public @Nonnull String read(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { @@ -289,9 +290,9 @@ public String read(JsonParser parser) } }; - public static final JsonReader BinaryReader = new JsonReader() + public static final @Nonnull JsonReader BinaryReader = new JsonReader() { - public byte[] read(JsonParser parser) + public @Nonnull byte[] read(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { @@ -307,16 +308,16 @@ public byte[] read(JsonParser parser) } }; - public static final JsonReader BooleanReader = new JsonReader() + public static final @Nonnull JsonReader BooleanReader = new JsonReader() { - public Boolean read(JsonParser parser) + public @Nonnull Boolean read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return readBoolean(parser); } }; - public static boolean readBoolean(JsonParser parser) + public static boolean readBoolean(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { @@ -329,7 +330,7 @@ public static boolean readBoolean(JsonParser parser) } } - public static double readDouble(JsonParser parser) + public static double readDouble(@Nonnull JsonParser parser) throws IOException, JsonReadException { try { @@ -341,9 +342,9 @@ public static double readDouble(JsonParser parser) } } - public static final JsonReader VoidReader = new JsonReader() + public static final @Nonnull JsonReader VoidReader = new JsonReader() { - public Object read(JsonParser parser) + public @Nullable Object read(@Nonnull JsonParser parser) throws IOException, JsonReadException { skipValue(parser); @@ -351,7 +352,7 @@ public Object read(JsonParser parser) } }; - public static T readEnum(JsonParser parser, HashMap values, T catch_all) + public static @Nonnull T readEnum(@Nonnull JsonParser parser, @Nonnull HashMap values, @Nullable T catch_all) throws IOException, JsonReadException { if (parser.getCurrentToken() == JsonToken.START_OBJECT) { @@ -406,15 +407,15 @@ public static final class FieldMapping // - The get() could take (char[], offset, length) instead of String, which we can // provide straight from JsonParser's internal buffer. This makes error reporting // tricky, though, because we won't have a string for addFieldContext. - public final HashMap fields; + public final @Nonnull HashMap fields; - private FieldMapping(HashMap fields) + private FieldMapping(@Nonnull HashMap fields) { assert fields != null; this.fields = fields; } - public int get(String fieldName) + public int get(@Nonnull String fieldName) { Integer i = fields.get(fieldName); if (i == null) return -1; @@ -423,9 +424,9 @@ public int get(String fieldName) public static final class Builder { - private /*@Nullable*/HashMap fields = new HashMap(); + private @Nullable HashMap fields = new HashMap(); - public void add(String fieldName, int expectedIndex) + public void add(@Nonnull String fieldName, int expectedIndex) { if (fields == null) throw new IllegalStateException("already called build(); can't call add() anymore"); int i = fields.size(); @@ -438,7 +439,7 @@ public void add(String fieldName, int expectedIndex) } } - public FieldMapping build() + public @Nonnull FieldMapping build() { if (fields == null) throw new IllegalStateException("already called build(); can't call build() again"); HashMap f = fields; @@ -450,7 +451,7 @@ public FieldMapping build() static final JsonFactory jsonFactory = new JsonFactory(); - public T readFully(InputStream utf8Body) + public @Nullable T readFully(@Nonnull InputStream utf8Body) throws IOException, JsonReadException { try { @@ -462,7 +463,7 @@ public T readFully(InputStream utf8Body) } } - public T readFully(String body) + public @Nullable T readFully(@Nonnull String body) throws JsonReadException { try { @@ -482,7 +483,7 @@ public T readFully(String body) } } - public T readFully(byte[] utf8Body) + public @Nullable T readFully(@Nonnull byte[] utf8Body) throws JsonReadException { try { @@ -502,13 +503,13 @@ public T readFully(byte[] utf8Body) } } - public T readFromFile(String filePath) + public @Nullable T readFromFile(@Nonnull String filePath) throws FileLoadException { return readFromFile(new File(filePath)); } - public T readFromFile(File file) + public @Nullable T readFromFile(@Nonnull File file) throws FileLoadException { try { @@ -531,7 +532,7 @@ public T readFromFile(File file) public static abstract class FileLoadException extends Exception { private static final long serialVersionUID = 0L; - protected FileLoadException(String message) + protected FileLoadException(@Nonnull String message) { super(message); } @@ -539,9 +540,9 @@ protected FileLoadException(String message) public static final class IOError extends FileLoadException { private static final long serialVersionUID = 0L; - public final IOException reason; + public final @Nonnull IOException reason; - public IOError(File file, IOException reason) + public IOError(@Nonnull File file, @Nonnull IOException reason) { super("unable to read file \"" + file.getPath() + "\": " + reason.getMessage()); this.reason = reason; @@ -551,9 +552,9 @@ public IOError(File file, IOException reason) public static final class JsonError extends FileLoadException { private static final long serialVersionUID = 0L; - public final JsonReadException reason; + public final @Nonnull JsonReadException reason; - public JsonError(File file, JsonReadException reason) + public JsonError(@Nonnull File file, @Nonnull JsonReadException reason) { super(file.getPath() + ": " + reason.getMessage()); this.reason = reason; @@ -561,7 +562,7 @@ public JsonError(File file, JsonReadException reason) } } - public T readFully(JsonParser parser) + public @Nullable T readFully(@Nonnull JsonParser parser) throws IOException, JsonReadException { parser.nextToken(); diff --git a/core/src/main/java/com/dropbox/core/json/JsonWriter.java b/core/src/main/java/com/dropbox/core/json/JsonWriter.java index 2eae5fa38..1de49fe84 100644 --- a/core/src/main/java/com/dropbox/core/json/JsonWriter.java +++ b/core/src/main/java/com/dropbox/core/json/JsonWriter.java @@ -13,33 +13,36 @@ import com.dropbox.core.json.JsonDateReader; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public abstract class JsonWriter { - private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + private static final @Nonnull TimeZone UTC = TimeZone.getTimeZone("UTC"); + private static final @Nonnull String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; - public static String formatDate(Date date) { + public static @Nonnull String formatDate(@Nonnull Date date) { DateFormat df = new SimpleDateFormat(DATE_FORMAT); df.setTimeZone(UTC); return df.format(date); } - public abstract void write(T value, JsonGenerator g) + public abstract void write(@Nullable T value, @Nonnull JsonGenerator g) throws IOException; - public void write(T value, JsonGenerator g, int level) + public void write(@Nullable T value, @Nonnull JsonGenerator g, int level) throws IOException { write(value, g); } - public void writeFields(T value, JsonGenerator g) + public void writeFields(@Nullable T value, @Nonnull JsonGenerator g) throws IOException { // Default does nothing. Override for struct fields. } - public final String writeToString(T value, boolean indent) + public final @Nonnull String writeToString(@Nullable T value, boolean indent) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { @@ -62,12 +65,12 @@ public final String writeToString(T value, boolean indent) } } - public final String writeToString(T value) + public final @Nonnull String writeToString(@Nullable T value) { return writeToString(value, true); } - public final void writeToStream(T value, OutputStream out, boolean indent) + public final void writeToStream(@Nullable T value, @Nonnull OutputStream out, boolean indent) throws IOException { JsonGenerator g = JsonReader.jsonFactory.createGenerator(out); @@ -82,13 +85,13 @@ public final void writeToStream(T value, OutputStream out, boolean indent) } } - public final void writeToStream(T value, OutputStream out) + public final void writeToStream(@Nullable T value, @Nonnull OutputStream out) throws IOException { writeToStream(value, out, true); } - public final void writeToFile(T value, File file, boolean indent) + public final void writeToFile(@Nullable T value, @Nonnull File file, boolean indent) throws IOException { FileOutputStream fout = new FileOutputStream(file); @@ -100,25 +103,25 @@ public final void writeToFile(T value, File file, boolean indent) } } - public final void writeToFile(T value, File file) + public final void writeToFile(@Nullable T value, @Nonnull File file) throws IOException { writeToFile(value, file, true); } - public final void writeToFile(T value, String fileName, boolean indent) + public final void writeToFile(@Nullable T value, @Nonnull String fileName, boolean indent) throws IOException { writeToFile(value, new File(fileName), indent); } - public final void writeToFile(T value, String fileName) + public final void writeToFile(@Nullable T value, @Nonnull String fileName) throws IOException { writeToFile(value, fileName, true); } - public final void writeDateIso(java.util.Date date, JsonGenerator g) + public final void writeDateIso(@Nonnull java.util.Date date, @Nonnull JsonGenerator g) throws IOException { g.writeString(formatDate(date)); @@ -127,7 +130,7 @@ public final void writeDateIso(java.util.Date date, JsonGenerator g) static private final String weekdays[] = {null, "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static private final String months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", null}; - public final void writeDate(java.util.Date date, JsonGenerator g) + public final void writeDate(@Nonnull java.util.Date date, @Nonnull JsonGenerator g) throws IOException { GregorianCalendar c = new GregorianCalendar(JsonDateReader.UTC); @@ -150,7 +153,7 @@ public final void writeDate(java.util.Date date, JsonGenerator g) g.writeString(buf.toString()); } - private static String zeroPad(String v, int desiredLength) + private static @Nonnull String zeroPad(@Nonnull String v, int desiredLength) { while (v.length() < desiredLength) { v = "0" + v; diff --git a/core/src/main/java/com/dropbox/core/oauth/DbxCredential.java b/core/src/main/java/com/dropbox/core/oauth/DbxCredential.java index 052a86172..a9596ee02 100644 --- a/core/src/main/java/com/dropbox/core/oauth/DbxCredential.java +++ b/core/src/main/java/com/dropbox/core/oauth/DbxCredential.java @@ -1,5 +1,7 @@ package com.dropbox.core.oauth; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.DbxException; import com.dropbox.core.DbxHost; import com.dropbox.core.DbxRequestConfig; @@ -24,8 +26,6 @@ import static com.dropbox.core.oauth.DbxOAuthError.INVALID_REQUEST; -/*>>> import checkers.nullness.quals.NonNull; */ -/*>>> import checkers.nullness.quals.Nullable; */ /** * @@ -44,18 +44,18 @@ public class DbxCredential { */ public final static long EXPIRE_MARGIN = 5 * 60 * 1000; // 5 minutes - private String accessToken; - private /*@Nullable*/Long expiresAt; - private final String refreshToken; - private final String appKey; - private final String appSecret; + private @Nonnull String accessToken; + private @Nullable Long expiresAt; + private final @Nullable String refreshToken; + private final @Nullable String appKey; + private final @Nullable String appSecret; /** * Create a DbxCredential object that doesn't support refreshing. * * @param accessToken Short live token or legacty long live token. */ - public DbxCredential(String accessToken) { + public DbxCredential(@Nonnull String accessToken) { this(accessToken, null, null, null, null); } @@ -68,8 +68,10 @@ public DbxCredential(String accessToken) { * @param refreshToken Refresh token from OAuth flow. * @param appKey You app's client id. */ - public DbxCredential(String accessToken, /*Nullable*/Long expiresAt, String refreshToken, String - appKey) { + public DbxCredential(@Nonnull String accessToken, + @Nullable Long expiresAt, + @Nullable String refreshToken, + @Nullable String appKey) { this(accessToken, expiresAt, refreshToken, appKey, null); } @@ -82,7 +84,11 @@ public DbxCredential(String accessToken, /*Nullable*/Long expiresAt, String refr * @param appKey You app's client id. * @param appSecret You app's client secret. */ - public DbxCredential(String accessToken, /*@Nullable*/Long expiresAt, String refreshToken, String appKey, String appSecret) { + public DbxCredential(@Nonnull String accessToken, + @Nullable Long expiresAt, + @Nullable String refreshToken, + @Nullable String appKey, + @Nullable String appSecret) { if (accessToken == null) { throw new IllegalArgumentException("Missing access token."); } @@ -107,7 +113,7 @@ public DbxCredential(String accessToken, /*@Nullable*/Long expiresAt, String ref * * @return OAuth access token */ - public String getAccessToken() { + public @Nonnull String getAccessToken() { return this.accessToken; } @@ -117,15 +123,15 @@ public String getAccessToken() { * * @return ExpiresAt in millisecond. */ - public Long getExpiresAt() { + public @Nullable Long getExpiresAt() { return this.expiresAt; } - public String getAppKey() { + public @Nullable String getAppKey() { return this.appKey; } - public String getAppSecret() { + public @Nullable String getAppSecret() { return this.appSecret; } @@ -135,7 +141,7 @@ public String getAppSecret() { * * @return Refresh Token. */ - public String getRefreshToken() { + public @Nullable String getRefreshToken() { return this.refreshToken; } @@ -162,8 +168,9 @@ public boolean aboutToExpire() { * refresh token is revoked. * @throws DbxException If refresh failed for general errors. */ - public DbxRefreshResult refresh(DbxRequestConfig requestConfig, DbxHost host, - Collection scope) + public @Nonnull DbxRefreshResult refresh(@Nonnull DbxRequestConfig requestConfig, + @Nonnull DbxHost host, + @Nullable Collection scope) throws DbxException { if (this.refreshToken == null) { throw new DbxOAuthException(null, new DbxOAuthError(INVALID_REQUEST, "Cannot refresh becasue there is no refresh token")); @@ -202,7 +209,7 @@ public DbxRefreshResult refresh(DbxRequestConfig requestConfig, DbxHost host, headers, new DbxRequestUtil.ResponseHandler() { @Override - public DbxRefreshResult handle(HttpRequestor.Response response) throws DbxException { + public @Nonnull DbxRefreshResult handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) { String requestId = DbxRequestUtil.getRequestId(response); DbxOAuthError dbxOAuthError = DbxRequestUtil.readJsonFromResponse( @@ -232,7 +239,7 @@ public DbxRefreshResult handle(HttpRequestor.Response response) throws DbxExcept * refresh token is invalid or revoked. * @throws DbxException If refresh failed for general errors. */ - public DbxRefreshResult refresh(DbxRequestConfig requestConfig) throws DbxException { + public @Nonnull DbxRefreshResult refresh(@Nonnull DbxRequestConfig requestConfig) throws DbxException { return refresh(requestConfig, DbxHost.DEFAULT, null); } @@ -249,7 +256,8 @@ public DbxRefreshResult refresh(DbxRequestConfig requestConfig) throws DbxExcept * refresh token is invalid or revoked. * @throws DbxException If refresh failed for general errors. */ - public DbxRefreshResult refresh(DbxRequestConfig requestConfig, Collection scope) throws + public @Nonnull DbxRefreshResult refresh(@Nonnull DbxRequestConfig requestConfig, + @Nullable Collection scope) throws DbxException { return refresh(requestConfig, DbxHost.DEFAULT, scope); } @@ -258,14 +266,14 @@ public DbxRefreshResult refresh(DbxRequestConfig requestConfig, Collection Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public final DbxCredential read(JsonParser parser) + public final @Nonnull DbxCredential read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -314,10 +322,10 @@ else if (fieldName.equals("app_secret")) { } }; - public static final JsonWriter Writer = new JsonWriter() + public static final @Nonnull JsonWriter Writer = new JsonWriter() { @Override - public void write(DbxCredential credential, JsonGenerator g) throws IOException + public void write(@Nonnull DbxCredential credential, @Nonnull JsonGenerator g) throws IOException { g.writeStartObject(); g.writeStringField("access_token", credential.accessToken); diff --git a/core/src/main/java/com/dropbox/core/oauth/DbxOAuthError.java b/core/src/main/java/com/dropbox/core/oauth/DbxOAuthError.java index a5a91ce32..ae5d27f7c 100644 --- a/core/src/main/java/com/dropbox/core/oauth/DbxOAuthError.java +++ b/core/src/main/java/com/dropbox/core/oauth/DbxOAuthError.java @@ -11,6 +11,9 @@ import java.util.HashSet; import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * * This class provides deserialization for the error response returned from OAuth endpoint. @@ -18,17 +21,17 @@ * @see https://tools.ietf.org/html/rfc6749#section-5.2 */ public class DbxOAuthError { - public final static String INVALID_REQUEST = "invalid_request"; - public final static String INVALID_GRANT = "invalid_grant"; - public final static String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"; - public final static String UNKNOWN = "unknown"; - public final static Set ERRORS = new HashSet(Arrays.asList(INVALID_REQUEST, + public final static @Nonnull String INVALID_REQUEST = "invalid_request"; + public final static @Nonnull String INVALID_GRANT = "invalid_grant"; + public final static @Nonnull String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"; + public final static @Nonnull String UNKNOWN = "unknown"; + public final static @Nonnull Set ERRORS = new HashSet(Arrays.asList(INVALID_REQUEST, INVALID_GRANT, UNSUPPORTED_GRANT_TYPE)); - private final String error; - private final String errorDescription; + private final @Nonnull String error; + private final @Nullable String errorDescription; - public DbxOAuthError(String error, String errorDescription) { + public DbxOAuthError(@Nonnull String error, @Nullable String errorDescription) { if (ERRORS.contains(error)) { this.error = error; } else { @@ -38,18 +41,18 @@ public DbxOAuthError(String error, String errorDescription) { this.errorDescription = errorDescription; } - public String getError() { + public @Nonnull String getError() { return this.error; } - public String getErrorDescription() { + public @Nullable String getErrorDescription() { return this.errorDescription; } - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public final DbxOAuthError read(JsonParser parser) + public final @Nonnull DbxOAuthError read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); diff --git a/core/src/main/java/com/dropbox/core/oauth/DbxOAuthException.java b/core/src/main/java/com/dropbox/core/oauth/DbxOAuthException.java index 5056126ed..ac04509ff 100644 --- a/core/src/main/java/com/dropbox/core/oauth/DbxOAuthException.java +++ b/core/src/main/java/com/dropbox/core/oauth/DbxOAuthException.java @@ -2,15 +2,18 @@ import com.dropbox.core.DbxException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * * This exception means OAuth endpoint has thrown error. */ public class DbxOAuthException extends DbxException { private static final long serialVersionUID = 0L; - private final DbxOAuthError dbxOAuthError; + private final @Nonnull DbxOAuthError dbxOAuthError; - public DbxOAuthException(String requestId, DbxOAuthError dbxOAuthError) { + public DbxOAuthException(@Nullable String requestId, @Nonnull DbxOAuthError dbxOAuthError) { super(requestId, dbxOAuthError.getErrorDescription()); this.dbxOAuthError = dbxOAuthError; } @@ -19,7 +22,7 @@ public DbxOAuthException(String requestId, DbxOAuthError dbxOAuthError) { * Get the wrapped {@link DbxOAuthError} to tell what error has been thrown. * @return {@link DbxOAuthError} contains what error has been thrown. */ - public DbxOAuthError getDbxOAuthError() { + public @Nonnull DbxOAuthError getDbxOAuthError() { return dbxOAuthError; } } diff --git a/core/src/main/java/com/dropbox/core/oauth/DbxRefreshResult.java b/core/src/main/java/com/dropbox/core/oauth/DbxRefreshResult.java index 0539fb0f3..01ab476c0 100644 --- a/core/src/main/java/com/dropbox/core/oauth/DbxRefreshResult.java +++ b/core/src/main/java/com/dropbox/core/oauth/DbxRefreshResult.java @@ -1,5 +1,7 @@ package com.dropbox.core.oauth; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.DbxAuthFinish; import com.dropbox.core.DbxRequestConfig; import com.dropbox.core.json.JsonReadException; @@ -10,7 +12,6 @@ import java.io.IOException; -/*>>> import checkers.nullness.quals.NonNull; */ /** @@ -18,17 +19,17 @@ * access token and expiration time. */ public class DbxRefreshResult { - private final String accessToken; + private final @Nonnull String accessToken; private final long expiresIn; /* in seconds */ private long issueTime; /* in milliseconds */ - private String scope; + private @Nullable String scope; /** * @param accessToken OAuth access token. * @param expiresIn Duration time of accessToken in second. * was passed */ - public DbxRefreshResult(/*@NotNull*/String accessToken, long expiresIn) { + public DbxRefreshResult(@Nonnull String accessToken, long expiresIn) { this(accessToken, expiresIn, null); } @@ -37,7 +38,7 @@ public DbxRefreshResult(/*@NotNull*/String accessToken, long expiresIn) { * @param expiresIn Duration time of accessToken in second. * was passed */ - public DbxRefreshResult(/*@NotNull*/String accessToken, long expiresIn, String scope) { + public DbxRefreshResult(@Nonnull String accessToken, long expiresIn, @Nullable String scope) { if (accessToken == null) { throw new IllegalArgumentException("access token can't be null."); } @@ -53,7 +54,7 @@ public DbxRefreshResult(/*@NotNull*/String accessToken, long expiresIn, String s * * @return OAuth access token used for authorization with Dropbox servers */ - public String getAccessToken() { + public @Nonnull String getAccessToken() { return accessToken; } @@ -63,7 +64,7 @@ public String getAccessToken() { * * @return OAuth access token used for authorization with Dropbox servers */ - public Long getExpiresAt() { + public @Nonnull Long getExpiresAt() { return issueTime + expiresIn * 1000; } @@ -71,7 +72,7 @@ public Long getExpiresAt() { * @return If you specified a subset of original scope in refresh call, this value shows what * permissions the new short lived token has. */ - public String getScope() { + public @Nullable String getScope() { return scope; } @@ -85,8 +86,8 @@ void setIssueTime(long issueTime) { /** * For JSON parsing. */ - public static final JsonReader Reader = new JsonReader() { - public DbxRefreshResult read(JsonParser parser) throws IOException, JsonReadException { + public static final @Nonnull JsonReader Reader = new JsonReader() { + public @Nonnull DbxRefreshResult read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); String tokenType = null; diff --git a/core/src/main/java/com/dropbox/core/stone/CompositeSerializer.java b/core/src/main/java/com/dropbox/core/stone/CompositeSerializer.java index acad464ba..fe3b440f6 100644 --- a/core/src/main/java/com/dropbox/core/stone/CompositeSerializer.java +++ b/core/src/main/java/com/dropbox/core/stone/CompositeSerializer.java @@ -8,14 +8,17 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public abstract class CompositeSerializer extends StoneSerializer { - protected static final String TAG_FIELD = ".tag"; + protected static final @Nonnull String TAG_FIELD = ".tag"; - protected static boolean hasTag(JsonParser p) throws IOException, JsonParseException { + protected static boolean hasTag(@Nonnull JsonParser p) throws IOException, JsonParseException { return p.getCurrentToken() == JsonToken.FIELD_NAME && TAG_FIELD.equals(p.getCurrentName()); } - protected static String readTag(JsonParser p) throws IOException, JsonParseException { + protected static @Nullable String readTag(@Nonnull JsonParser p) throws IOException, JsonParseException { if (!hasTag(p)) { return null; } @@ -26,10 +29,9 @@ protected static String readTag(JsonParser p) throws IOException, JsonParseExcep return tag; } - protected void writeTag(String tag, JsonGenerator g) throws IOException, JsonGenerationException { + protected void writeTag(@Nullable String tag, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { if (tag != null) { g.writeStringField(TAG_FIELD, tag); } } } - diff --git a/core/src/main/java/com/dropbox/core/stone/StoneDeserializerLogger.java b/core/src/main/java/com/dropbox/core/stone/StoneDeserializerLogger.java index c7593ba71..ecb5c6b96 100644 --- a/core/src/main/java/com/dropbox/core/stone/StoneDeserializerLogger.java +++ b/core/src/main/java/com/dropbox/core/stone/StoneDeserializerLogger.java @@ -3,24 +3,30 @@ import java.util.HashMap; import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public class StoneDeserializerLogger { - public static Map, LoggerCallback> LOGGER_MAP = + public static @Nonnull Map, LoggerCallback> LOGGER_MAP = new HashMap, LoggerCallback>(); - public static void registerCallback(Class c, LoggerCallback callback) { + public static void registerCallback(@Nonnull Class c, @Nonnull LoggerCallback callback) { LOGGER_MAP.put(c, callback); } - public static void log(Object value, String multiLineLog) { + public static void log(@Nonnull Object value, @Nonnull String multiLineLog) { Class c = value.getClass(); if (LOGGER_MAP.containsKey(c)) { - LoggerCallback callback = LOGGER_MAP.get(c); + @Nullable LoggerCallback callback = LOGGER_MAP.get(c); + if (callback == null) { + return; + } callback.invoke(value, multiLineLog); } } public interface LoggerCallback { - public void invoke(Object value, String multiLineLog); + public void invoke(@Nonnull Object value, @Nonnull String multiLineLog); } } diff --git a/core/src/main/java/com/dropbox/core/stone/StoneSerializer.java b/core/src/main/java/com/dropbox/core/stone/StoneSerializer.java index 8cd946e82..e53fb28ea 100644 --- a/core/src/main/java/com/dropbox/core/stone/StoneSerializer.java +++ b/core/src/main/java/com/dropbox/core/stone/StoneSerializer.java @@ -12,14 +12,17 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public abstract class StoneSerializer { - private static final Charset UTF8 = Charset.forName("UTF-8"); + private static final @Nonnull Charset UTF8 = Charset.forName("UTF-8"); - public String serialize(T value) { + public @Nonnull String serialize(@Nullable T value) { return serialize(value, false); } - public String serialize(T value, boolean pretty) { + public @Nonnull String serialize(@Nullable T value, boolean pretty) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { serialize(value, out, pretty); @@ -31,11 +34,11 @@ public String serialize(T value, boolean pretty) { return new String(out.toByteArray(), UTF8); } - public void serialize(T value, OutputStream out) throws IOException { + public void serialize(@Nullable T value, @Nonnull OutputStream out) throws IOException { serialize(value, out, false); } - public void serialize(T value, OutputStream out, boolean pretty) throws IOException { + public void serialize(@Nullable T value, @Nonnull OutputStream out, boolean pretty) throws IOException { JsonGenerator g = Util.JSON.createGenerator(out); if (pretty) { g.useDefaultPrettyPrinter(); @@ -48,7 +51,7 @@ public void serialize(T value, OutputStream out, boolean pretty) throws IOExcept g.flush(); } - public T deserialize(String json) throws JsonParseException { + public @Nullable T deserialize(@Nonnull String json) throws JsonParseException { try { JsonParser p = Util.JSON.createParser(json); p.nextToken(); @@ -60,23 +63,23 @@ public T deserialize(String json) throws JsonParseException { } } - public T deserialize(InputStream json) throws IOException, JsonParseException { + public @Nullable T deserialize(@Nonnull InputStream json) throws IOException, JsonParseException { JsonParser p = Util.JSON.createParser(json); p.nextToken(); return deserialize(p); } - public abstract void serialize(T value, JsonGenerator g) throws IOException, JsonGenerationException; - public abstract T deserialize(JsonParser p) throws IOException, JsonParseException; + public abstract void serialize(@Nullable T value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException; + public abstract @Nullable T deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException; - protected static String getStringValue(JsonParser p) throws IOException, JsonParseException { + protected static @Nonnull String getStringValue(@Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken() != JsonToken.VALUE_STRING) { throw new JsonParseException(p, "expected string value, but was " + p.getCurrentToken()); } return p.getText(); } - protected static void expectField(String name, JsonParser p) throws IOException, JsonParseException { + protected static void expectField(@Nonnull String name, @Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken() != JsonToken.FIELD_NAME) { throw new JsonParseException(p, "expected field name, but was: " + p.getCurrentToken()); } @@ -86,35 +89,35 @@ protected static void expectField(String name, JsonParser p) throws IOException, p.nextToken(); } - protected static void expectStartObject(JsonParser p) throws IOException, JsonParseException { + protected static void expectStartObject(@Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken() != JsonToken.START_OBJECT) { throw new JsonParseException(p, "expected object value."); } p.nextToken(); } - protected static void expectEndObject(JsonParser p) throws IOException, JsonParseException { + protected static void expectEndObject(@Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken() != JsonToken.END_OBJECT) { throw new JsonParseException(p, "expected end of object value."); } p.nextToken(); } - protected static void expectStartArray(JsonParser p) throws IOException, JsonParseException { + protected static void expectStartArray(@Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken() != JsonToken.START_ARRAY) { throw new JsonParseException(p, "expected array value."); } p.nextToken(); } - protected static void expectEndArray(JsonParser p) throws IOException, JsonParseException { + protected static void expectEndArray(@Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken() != JsonToken.END_ARRAY) { throw new JsonParseException(p, "expected end of array value."); } p.nextToken(); } - protected static void skipValue(JsonParser p) throws IOException, JsonParseException { + protected static void skipValue(@Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken().isStructStart()) { p.skipChildren(); // will leave parser at end token (e.g. '}' or ']') p.nextToken(); @@ -125,7 +128,7 @@ protected static void skipValue(JsonParser p) throws IOException, JsonParseExcep } } - protected static void skipFields(JsonParser p) throws IOException, JsonParseException { + protected static void skipFields(@Nonnull JsonParser p) throws IOException, JsonParseException { while (p.getCurrentToken() != null && !p.getCurrentToken().isStructEnd()) { if (p.getCurrentToken().isStructStart()) { p.skipChildren(); diff --git a/core/src/main/java/com/dropbox/core/stone/StoneSerializers.java b/core/src/main/java/com/dropbox/core/stone/StoneSerializers.java index e1bca5538..6af8e273f 100644 --- a/core/src/main/java/com/dropbox/core/stone/StoneSerializers.java +++ b/core/src/main/java/com/dropbox/core/stone/StoneSerializers.java @@ -14,78 +14,81 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public final class StoneSerializers { - public static StoneSerializer uInt64() { + public static @Nonnull StoneSerializer uInt64() { return LongSerializer.INSTANCE; } - public static StoneSerializer int64() { + public static @Nonnull StoneSerializer int64() { return LongSerializer.INSTANCE; } - public static StoneSerializer uInt32() { + public static @Nonnull StoneSerializer uInt32() { return LongSerializer.INSTANCE; } - public static StoneSerializer int32() { + public static @Nonnull StoneSerializer int32() { return IntSerializer.INSTANCE; } - public static StoneSerializer float64() { + public static @Nonnull StoneSerializer float64() { return DoubleSerializer.INSTANCE; } - public static StoneSerializer float32() { + public static @Nonnull StoneSerializer float32() { return FloatSerializer.INSTANCE; } - public static StoneSerializer boolean_() { + public static @Nonnull StoneSerializer boolean_() { return BooleanSerializer.INSTANCE; } - public static StoneSerializer bytes() { + public static @Nonnull StoneSerializer bytes() { return ByteArraySerializer.INSTANCE; } - public static StoneSerializer string() { + public static @Nonnull StoneSerializer string() { return StringSerializer.INSTANCE; } - public static StoneSerializer timestamp() { + public static @Nonnull StoneSerializer timestamp() { return DateSerializer.INSTANCE; } - public static StoneSerializer void_() { + public static @Nonnull StoneSerializer void_() { return VoidSerializer.INSTANCE; } - public static StoneSerializer nullable(StoneSerializer underlying) { + public static @Nonnull StoneSerializer nullable(@Nonnull StoneSerializer underlying) { return new NullableSerializer(underlying); } - public static StructSerializer nullableStruct(StructSerializer underlying) { + public static @Nonnull StructSerializer nullableStruct(@Nonnull StructSerializer underlying) { return new NullableStructSerializer(underlying); } - public static StoneSerializer> list(StoneSerializer underlying) { + public static @Nonnull StoneSerializer> list(@Nonnull StoneSerializer underlying) { return new ListSerializer(underlying); } - public static StoneSerializer> map(StoneSerializer underlying) { + public static @Nonnull StoneSerializer> map(@Nonnull StoneSerializer underlying) { return new MapSerializer(underlying); } private static final class LongSerializer extends StoneSerializer { - public static final LongSerializer INSTANCE = new LongSerializer(); + public static final @Nonnull LongSerializer INSTANCE = new LongSerializer(); @Override - public void serialize(Long value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Long value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeNumber(value); } @Override - public Long deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull Long deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { Long value = p.getLongValue(); p.nextToken(); return value; @@ -93,15 +96,15 @@ public Long deserialize(JsonParser p) throws IOException, JsonParseException { } private static final class IntSerializer extends StoneSerializer { - public static final IntSerializer INSTANCE = new IntSerializer(); + public static final @Nonnull IntSerializer INSTANCE = new IntSerializer(); @Override - public void serialize(Integer value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Integer value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeNumber(value); } @Override - public Integer deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull Integer deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { Integer value = p.getIntValue(); p.nextToken(); return value; @@ -109,15 +112,15 @@ public Integer deserialize(JsonParser p) throws IOException, JsonParseException } private static final class DoubleSerializer extends StoneSerializer { - public static final DoubleSerializer INSTANCE = new DoubleSerializer(); + public static final @Nonnull DoubleSerializer INSTANCE = new DoubleSerializer(); @Override - public void serialize(Double value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Double value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeNumber(value); } @Override - public Double deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull Double deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { Double value = p.getDoubleValue(); p.nextToken(); return value; @@ -125,15 +128,15 @@ public Double deserialize(JsonParser p) throws IOException, JsonParseException { } private static final class FloatSerializer extends StoneSerializer { - public static final FloatSerializer INSTANCE = new FloatSerializer(); + public static final @Nonnull FloatSerializer INSTANCE = new FloatSerializer(); @Override - public void serialize(Float value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Float value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeNumber(value); } @Override - public Float deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull Float deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { Float value = p.getFloatValue(); p.nextToken(); return value; @@ -141,15 +144,15 @@ public Float deserialize(JsonParser p) throws IOException, JsonParseException { } private static final class BooleanSerializer extends StoneSerializer { - public static final BooleanSerializer INSTANCE = new BooleanSerializer(); + public static final @Nonnull BooleanSerializer INSTANCE = new BooleanSerializer(); @Override - public void serialize(Boolean value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Boolean value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeBoolean(value); } @Override - public Boolean deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull Boolean deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { Boolean value = p.getBooleanValue(); p.nextToken(); return value; @@ -157,15 +160,15 @@ public Boolean deserialize(JsonParser p) throws IOException, JsonParseException } private static final class ByteArraySerializer extends StoneSerializer { - public static final ByteArraySerializer INSTANCE = new ByteArraySerializer(); + public static final @Nonnull ByteArraySerializer INSTANCE = new ByteArraySerializer(); @Override - public void serialize(byte [] value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable byte [] value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeBinary(value); } @Override - public byte [] deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull byte [] deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { byte [] value = p.getBinaryValue(); p.nextToken(); return value; @@ -173,15 +176,15 @@ public void serialize(byte [] value, JsonGenerator g) throws IOException, JsonGe } private static final class StringSerializer extends StoneSerializer { - public static final StringSerializer INSTANCE = new StringSerializer(); + public static final @Nonnull StringSerializer INSTANCE = new StringSerializer(); @Override - public void serialize(String value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable String value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeString(value); } @Override - public String deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull String deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { String value = getStringValue(p); p.nextToken(); return value; @@ -189,15 +192,15 @@ public String deserialize(JsonParser p) throws IOException, JsonParseException { } private static final class DateSerializer extends StoneSerializer { - public static final DateSerializer INSTANCE = new DateSerializer(); + public static final @Nonnull DateSerializer INSTANCE = new DateSerializer(); @Override - public void serialize(Date value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Date value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeString(Util.formatTimestamp(value)); } @Override - public Date deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull Date deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { String text = getStringValue(p); p.nextToken(); try { @@ -209,29 +212,29 @@ public Date deserialize(JsonParser p) throws IOException, JsonParseException { } private static final class VoidSerializer extends StoneSerializer { - public static final VoidSerializer INSTANCE = new VoidSerializer(); + public static final @Nonnull VoidSerializer INSTANCE = new VoidSerializer(); @Override - public void serialize(Void value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Void value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeNull(); } @Override - public Void deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nullable Void deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { skipValue(p); return null; } } private static final class NullableSerializer extends StoneSerializer { - private final StoneSerializer underlying; + private final @Nonnull StoneSerializer underlying; - public NullableSerializer(StoneSerializer underlying) { + public NullableSerializer(@Nonnull StoneSerializer underlying) { this.underlying = underlying; } @Override - public void serialize(T value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable T value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { if (value == null) { g.writeNull(); } else { @@ -240,7 +243,7 @@ public void serialize(T value, JsonGenerator g) throws IOException, JsonGenerati } @Override - public T deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nullable T deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { if (p.getCurrentToken() == JsonToken.VALUE_NULL) { p.nextToken(); return null; @@ -251,14 +254,14 @@ public T deserialize(JsonParser p) throws IOException, JsonParseException { } private static final class NullableStructSerializer extends StructSerializer { - private final StructSerializer underlying; + private final @Nonnull StructSerializer underlying; - public NullableStructSerializer(StructSerializer underlying) { + public NullableStructSerializer(@Nonnull StructSerializer underlying) { this.underlying = underlying; } @Override - public void serialize(T value, JsonGenerator g) throws IOException { + public void serialize(@Nullable T value, @Nonnull JsonGenerator g) throws IOException { if (value == null) { g.writeNull(); } else { @@ -267,7 +270,7 @@ public void serialize(T value, JsonGenerator g) throws IOException { } @Override - public void serialize(T value, JsonGenerator g, boolean collapsed) throws IOException { + public void serialize(@Nullable T value, @Nonnull JsonGenerator g, boolean collapsed) throws IOException { if (value == null) { g.writeNull(); } else { @@ -276,7 +279,7 @@ public void serialize(T value, JsonGenerator g, boolean collapsed) throws IOExce } @Override - public T deserialize(JsonParser p) throws IOException { + public @Nullable T deserialize(@Nonnull JsonParser p) throws IOException { if (p.getCurrentToken() == JsonToken.VALUE_NULL) { p.nextToken(); return null; @@ -286,7 +289,7 @@ public T deserialize(JsonParser p) throws IOException { } @Override - public T deserialize(JsonParser p, boolean collapsed) throws IOException { + public @Nullable T deserialize(@Nonnull JsonParser p, boolean collapsed) throws IOException { if (p.getCurrentToken() == JsonToken.VALUE_NULL) { p.nextToken(); return null; @@ -297,14 +300,14 @@ public T deserialize(JsonParser p, boolean collapsed) throws IOException { } private static final class ListSerializer extends StoneSerializer> { - private final StoneSerializer underlying; + private final @Nonnull StoneSerializer underlying; - public ListSerializer(StoneSerializer underlying) { + public ListSerializer(@Nonnull StoneSerializer underlying) { this.underlying = underlying; } @Override - public void serialize(List value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable List value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeStartArray(value.size()); for (T elem : value) { underlying.serialize(elem, g); @@ -313,7 +316,7 @@ public void serialize(List value, JsonGenerator g) throws IOException, JsonGe } @Override - public List deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull List deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { expectStartArray(p); List list = new ArrayList(); while (p.getCurrentToken() != JsonToken.END_ARRAY) { @@ -326,14 +329,14 @@ public List deserialize(JsonParser p) throws IOException, JsonParseException } private static final class MapSerializer extends StoneSerializer> { - private final StoneSerializer underlying; + private final @Nonnull StoneSerializer underlying; - public MapSerializer(StoneSerializer underlying) { + public MapSerializer(@Nonnull StoneSerializer underlying) { this.underlying = underlying; } @Override - public void serialize(Map value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable Map value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { g.writeStartObject(); for (Map.Entry e : value.entrySet()) { g.writeFieldName(e.getKey()); @@ -343,7 +346,7 @@ public void serialize(Map value, JsonGenerator g) throws IOException, } @Override - public Map deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nonnull Map deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { Map map = new HashMap(); expectStartObject(p); diff --git a/core/src/main/java/com/dropbox/core/stone/StructSerializer.java b/core/src/main/java/com/dropbox/core/stone/StructSerializer.java index 279205db6..d7b02771f 100644 --- a/core/src/main/java/com/dropbox/core/stone/StructSerializer.java +++ b/core/src/main/java/com/dropbox/core/stone/StructSerializer.java @@ -7,19 +7,22 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public abstract class StructSerializer extends CompositeSerializer { @Override - public void serialize(T value, JsonGenerator g) throws IOException, JsonGenerationException { + public void serialize(@Nullable T value, @Nonnull JsonGenerator g) throws IOException, JsonGenerationException { serialize(value, g, false); } - public abstract void serialize(T value, JsonGenerator g, boolean collapse) throws IOException, JsonGenerationException; + public abstract void serialize(@Nullable T value, @Nonnull JsonGenerator g, boolean collapse) throws IOException, JsonGenerationException; @Override - public T deserialize(JsonParser p) throws IOException, JsonParseException { + public @Nullable T deserialize(@Nonnull JsonParser p) throws IOException, JsonParseException { return deserialize(p, false); } - public abstract T deserialize(JsonParser p, boolean collapsed) throws IOException, JsonParseException; + public abstract @Nullable T deserialize(@Nonnull JsonParser p, boolean collapsed) throws IOException, JsonParseException; } diff --git a/core/src/main/java/com/dropbox/core/stone/Util.java b/core/src/main/java/com/dropbox/core/stone/Util.java index 9600006ae..eb39ead36 100644 --- a/core/src/main/java/com/dropbox/core/stone/Util.java +++ b/core/src/main/java/com/dropbox/core/stone/Util.java @@ -10,22 +10,24 @@ import com.fasterxml.jackson.core.JsonFactory; +import javax.annotation.Nonnull; + final class Util { - public static final JsonFactory JSON = new JsonFactory(); + public static final @Nonnull JsonFactory JSON = new JsonFactory(); - private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); - private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; - private static final String DATE_FORMAT = "yyyy-MM-dd"; + private static final @Nonnull TimeZone UTC = TimeZone.getTimeZone("UTC"); + private static final @Nonnull String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + private static final @Nonnull String DATE_FORMAT = "yyyy-MM-dd"; private static final int LONG_FORMAT_LENGTH = DATE_TIME_FORMAT.replace("'", "").length(); private static final int SHORT_FORMAT_LENGTH = DATE_FORMAT.replace("'", "").length(); - public static String formatTimestamp(Date timestamp) { + public static @Nonnull String formatTimestamp(@Nonnull Date timestamp) { DateFormat format = new SimpleDateFormat(DATE_TIME_FORMAT, Locale.ENGLISH); format.setCalendar(new GregorianCalendar(UTC)); return format.format(timestamp); } - public static Date parseTimestamp(String timestamp) throws ParseException { + public static @Nonnull Date parseTimestamp(@Nonnull String timestamp) throws ParseException { int length = timestamp.length(); DateFormat format = null; diff --git a/core/src/main/java/com/dropbox/core/util/Collector.java b/core/src/main/java/com/dropbox/core/util/Collector.java index a8d769fcf..8bc075750 100644 --- a/core/src/main/java/com/dropbox/core/util/Collector.java +++ b/core/src/main/java/com/dropbox/core/util/Collector.java @@ -1,25 +1,26 @@ package com.dropbox.core.util; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.ArrayList; -/*>>> import checkers.nullness.quals.Nullable; */ public abstract class Collector { - public abstract void add(E element); - public abstract L finish(); + public abstract void add(@Nullable E element); + public abstract @Nonnull L finish(); public static final class ArrayListCollector extends Collector> { - private /*@Nullable*/ArrayList list = new ArrayList(); + private @Nullable ArrayList list = new ArrayList(); - public void add(E element) + public void add(@Nullable E element) { if (list == null) throw new IllegalStateException("already called finish()"); this.list.add(element); } - public ArrayList finish() + public @Nonnull ArrayList finish() { ArrayList list = this.list; if (list == null) throw new IllegalStateException("already called finish()"); @@ -28,28 +29,28 @@ public ArrayList finish() } } - public static final class NullSkipper extends Collector + public static final class NullSkipper extends Collector { - private final Collector underlying; + private final @Nonnull Collector underlying; - public NullSkipper(Collector underlying) + public NullSkipper(@Nonnull Collector underlying) { this.underlying = underlying; } - public static Collector mk(Collector underlying) + public static @Nonnull Collector mk(@Nonnull Collector underlying) { return new NullSkipper(underlying); } - public void add(/*@Nullable*/E element) + public void add(@Nullable E element) { if (element != null) { underlying.add(element); } } - public L finish() + public @Nonnull L finish() { return underlying.finish(); } diff --git a/core/src/main/java/com/dropbox/core/util/CountingOutputStream.java b/core/src/main/java/com/dropbox/core/util/CountingOutputStream.java index dd548c53b..5f0040eb8 100644 --- a/core/src/main/java/com/dropbox/core/util/CountingOutputStream.java +++ b/core/src/main/java/com/dropbox/core/util/CountingOutputStream.java @@ -3,12 +3,14 @@ import java.io.IOException; import java.io.OutputStream; +import javax.annotation.Nonnull; + public class CountingOutputStream extends OutputStream { - private final OutputStream out; + private final @Nonnull OutputStream out; private long bytesWritten = 0; - public CountingOutputStream(OutputStream out) + public CountingOutputStream(@Nonnull OutputStream out) { this.out = out; } @@ -26,14 +28,14 @@ public void write(int b) throws IOException } @Override - public void write(byte[] b) throws IOException + public void write(@Nonnull byte[] b) throws IOException { bytesWritten += b.length; out.write(b); } @Override - public void write(byte[] b, int off, int len) throws IOException + public void write(@Nonnull byte[] b, int off, int len) throws IOException { bytesWritten += len; out.write(b, off, len); diff --git a/core/src/main/java/com/dropbox/core/util/DumpWriter.java b/core/src/main/java/com/dropbox/core/util/DumpWriter.java index d500363b9..0e14c0f21 100644 --- a/core/src/main/java/com/dropbox/core/util/DumpWriter.java +++ b/core/src/main/java/com/dropbox/core/util/DumpWriter.java @@ -1,21 +1,22 @@ package com.dropbox.core.util; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.json.JsonDateReader; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; -/*>>> import checkers.nullness.quals.Nullable; */ public abstract class DumpWriter { - public abstract DumpWriter recordStart(/*@Nullable*/String name); - public abstract DumpWriter recordEnd(); - public abstract DumpWriter f(String name); // Write a field name. You should write a value after. - public abstract DumpWriter listStart(); - public abstract DumpWriter listEnd(); - public abstract DumpWriter verbatim(String s); + public abstract @Nonnull DumpWriter recordStart(@Nullable String name); + public abstract @Nonnull DumpWriter recordEnd(); + public abstract @Nonnull DumpWriter f(@Nonnull String name); // Write a field name. You should write a value after. + public abstract @Nonnull DumpWriter listStart(); + public abstract @Nonnull DumpWriter listEnd(); + public abstract @Nonnull DumpWriter verbatim(@Nonnull String s); public static final class Multiline extends DumpWriter { @@ -23,7 +24,7 @@ public static final class Multiline extends DumpWriter private final int indentAmount; private int currentIndent; - public Multiline(StringBuilder buf, int indentAmount, int currentIndent, boolean nl) + public Multiline(@Nonnull StringBuilder buf, int indentAmount, int currentIndent, boolean nl) { if (buf == null) throw new IllegalArgumentException("'buf' must not be null"); if (indentAmount < 0) throw new IllegalArgumentException("'indentAmount' must be non-negative"); @@ -34,7 +35,7 @@ public Multiline(StringBuilder buf, int indentAmount, int currentIndent, boolean this.nl = nl; } - public Multiline(StringBuilder buf, int indentAmount, boolean nl) + public Multiline(@Nonnull StringBuilder buf, int indentAmount, boolean nl) { this(buf, indentAmount, 0, nl); } @@ -63,7 +64,7 @@ private void indentLess() } @Override - public DumpWriter recordStart(/*@Nullable*/String name) + public @Nonnull DumpWriter recordStart(@Nullable String name) { prefix(); if (name != null) { @@ -76,7 +77,7 @@ public DumpWriter recordStart(/*@Nullable*/String name) } @Override - public DumpWriter recordEnd() + public @Nonnull DumpWriter recordEnd() { if (!nl) throw new AssertionError("called recordEnd() in a bad state"); indentLess(); @@ -87,7 +88,7 @@ public DumpWriter recordEnd() } @Override - public DumpWriter f(String name) + public @Nonnull DumpWriter f(@Nonnull String name) { if (!nl) throw new AssertionError("called fieldStart() in a bad state"); prefix(); @@ -97,7 +98,7 @@ public DumpWriter f(String name) } @Override - public DumpWriter listStart() + public @Nonnull DumpWriter listStart() { prefix(); buf.append("[\n"); @@ -107,7 +108,7 @@ public DumpWriter listStart() } @Override - public DumpWriter listEnd() + public @Nonnull DumpWriter listEnd() { if (!nl) throw new AssertionError("called listEnd() in a bad state"); indentLess(); @@ -118,7 +119,7 @@ public DumpWriter listEnd() } @Override - public DumpWriter verbatim(String s) + public @Nonnull DumpWriter verbatim(@Nonnull String s) { prefix(); buf.append(s); @@ -132,7 +133,7 @@ public static final class Plain extends DumpWriter { private StringBuilder buf; - public Plain(StringBuilder buf) + public Plain(@Nonnull StringBuilder buf) { this.buf = buf; } @@ -149,7 +150,7 @@ private void sep() } @Override - public DumpWriter recordStart(/*@Nullable*/String name) + public @Nonnull DumpWriter recordStart(@Nullable String name) { if (name != null) { buf.append(name); @@ -160,7 +161,7 @@ public DumpWriter recordStart(/*@Nullable*/String name) } @Override - public DumpWriter recordEnd() + public @Nonnull DumpWriter recordEnd() { buf.append(")"); needSep = true; @@ -168,7 +169,7 @@ public DumpWriter recordEnd() } @Override - public DumpWriter f(String name) + public @Nonnull DumpWriter f(@Nonnull String name) { sep(); buf.append(name).append('='); @@ -177,7 +178,7 @@ public DumpWriter f(String name) } @Override - public DumpWriter listStart() + public @Nonnull DumpWriter listStart() { sep(); buf.append("["); @@ -186,7 +187,7 @@ public DumpWriter listStart() } @Override - public DumpWriter listEnd() + public @Nonnull DumpWriter listEnd() { buf.append("]"); needSep = true; @@ -194,7 +195,7 @@ public DumpWriter listEnd() } @Override - public DumpWriter verbatim(String s) + public @Nonnull DumpWriter verbatim(@Nonnull String s) { sep(); buf.append(s); @@ -202,12 +203,12 @@ public DumpWriter verbatim(String s) } } - public DumpWriter fieldVerbatim(String name, String s) + public @Nonnull DumpWriter fieldVerbatim(@Nonnull String name, @Nonnull String s) { return f(name).verbatim(s); } - public DumpWriter v(/*@Nullable*/Iterable list) + public @Nonnull DumpWriter v(@Nullable Iterable list) { if (list == null) { verbatim("null"); @@ -221,7 +222,7 @@ public DumpWriter v(/*@Nullable*/Iterable list) return this; } - public DumpWriter v(/*@Nullable*/String v) + public @Nonnull DumpWriter v(@Nullable String v) { if (v == null) { verbatim("null"); @@ -231,15 +232,15 @@ public DumpWriter v(/*@Nullable*/String v) return this; } - public DumpWriter v(int v) { return verbatim(Integer.toString(v)); } - public DumpWriter v(long v) { return verbatim(Long.toString(v)); } - public DumpWriter v(boolean v) { return verbatim(Boolean.toString(v)); } - public DumpWriter v(float v) { return verbatim(Float.toString(v)); } - public DumpWriter v(double v) { return verbatim(Double.toString(v)); } - public DumpWriter v(/*@Nullable*/Date v) { return verbatim(toStringDate(v)); } - public DumpWriter v(/*@Nullable*/Long v) { return verbatim(v == null ? "null" : Long.toString(v)); } + public @Nonnull DumpWriter v(int v) { return verbatim(Integer.toString(v)); } + public @Nonnull DumpWriter v(long v) { return verbatim(Long.toString(v)); } + public @Nonnull DumpWriter v(boolean v) { return verbatim(Boolean.toString(v)); } + public @Nonnull DumpWriter v(float v) { return verbatim(Float.toString(v)); } + public @Nonnull DumpWriter v(double v) { return verbatim(Double.toString(v)); } + public @Nonnull DumpWriter v(@Nullable Date v) { return verbatim(toStringDate(v)); } + public @Nonnull DumpWriter v(@Nullable Long v) { return verbatim(v == null ? "null" : Long.toString(v)); } - public DumpWriter v(/*@Nullable*/Dumpable v) + public @Nonnull DumpWriter v(@Nullable Dumpable v) { if (v == null) { verbatim("null"); @@ -252,7 +253,7 @@ public DumpWriter v(/*@Nullable*/Dumpable v) return this; } - public static String toStringDate(/*@Nullable*/Date date) + public static @Nonnull String toStringDate(@Nullable Date date) { if (date == null) { return "null"; diff --git a/core/src/main/java/com/dropbox/core/util/Dumpable.java b/core/src/main/java/com/dropbox/core/util/Dumpable.java index 0fc5c46e6..8a76bb2a0 100644 --- a/core/src/main/java/com/dropbox/core/util/Dumpable.java +++ b/core/src/main/java/com/dropbox/core/util/Dumpable.java @@ -1,6 +1,7 @@ package com.dropbox.core.util; -/*>>> import checkers.nullness.quals.Nullable; */ +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * A common superclass for pure-data classes. Contains a function to dump @@ -8,14 +9,14 @@ */ public abstract class Dumpable { - public final String toString() + public final @Nonnull String toString() { StringBuilder buf = new StringBuilder(); toString(buf); return buf.toString(); } - public final void toString(StringBuilder buf) + public final void toString(@Nonnull StringBuilder buf) { new DumpWriter.Plain(buf).v(this); } @@ -29,7 +30,7 @@ public final void toString(StringBuilder buf) * may change the format. *

*/ - public final String toStringMultiline() + public final @Nonnull String toStringMultiline() { StringBuilder buf = new StringBuilder(); toStringMultiline(buf, 0, true); @@ -52,11 +53,11 @@ public final String toStringMultiline() * Whether you will start displaying this value on its own line (and will need indentation * on the first line) or not. */ - public final void toStringMultiline(StringBuilder buf, int currentIndent, boolean nl) + public final void toStringMultiline(@Nonnull StringBuilder buf, int currentIndent, boolean nl) { new DumpWriter.Multiline(buf, 2, currentIndent, nl).v(this); } - protected /*@Nullable*/String getTypeName() { return null; } - protected abstract void dumpFields(DumpWriter out); + protected @Nullable String getTypeName() { return null; } + protected abstract void dumpFields(@Nonnull DumpWriter out); } diff --git a/core/src/main/java/com/dropbox/core/util/IOUtil.java b/core/src/main/java/com/dropbox/core/util/IOUtil.java index 81166ac81..7afefe47a 100644 --- a/core/src/main/java/com/dropbox/core/util/IOUtil.java +++ b/core/src/main/java/com/dropbox/core/util/IOUtil.java @@ -16,20 +16,23 @@ import java.io.Writer; import java.nio.charset.CharacterCodingException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public class IOUtil { public static final int DEFAULT_COPY_BUFFER_SIZE = 16 << 10; // 16 KiB - public static Reader utf8Reader(InputStream in) { + public static @Nonnull Reader utf8Reader(@Nonnull InputStream in) { // NOTE: Just passing StringUtil.UTF8 instead of StringUtil.UTF8.newDecoder() would be wrong. // The former will cause the InputStreamReader to ignore UTF-8 errors in the input. return new InputStreamReader(in, StringUtil.UTF8.newDecoder()); } - public static Writer utf8Writer(OutputStream out) { + public static @Nonnull Writer utf8Writer(@Nonnull OutputStream out) { return new OutputStreamWriter(out, StringUtil.UTF8.newEncoder()); } - public static String toUtf8String(InputStream in) throws ReadException, CharacterCodingException { + public static @Nonnull String toUtf8String(@Nonnull InputStream in) throws ReadException, CharacterCodingException { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { copyStreamToStream(in, out); @@ -39,11 +42,11 @@ public static String toUtf8String(InputStream in) throws ReadException, Characte return StringUtil.utf8ToString(out.toByteArray()); } - public static void copyStreamToStream(InputStream in, OutputStream out) throws ReadException, WriteException { + public static void copyStreamToStream(@Nonnull InputStream in, @Nonnull OutputStream out) throws ReadException, WriteException { copyStreamToStream(in, out, DEFAULT_COPY_BUFFER_SIZE); } - public static void copyStreamToStream(InputStream in, OutputStream out, byte[] copyBuffer) + public static void copyStreamToStream(@Nonnull InputStream in, @Nonnull OutputStream out, @Nonnull byte[] copyBuffer) throws ReadException, WriteException { while (true) { int count; @@ -63,16 +66,16 @@ public static void copyStreamToStream(InputStream in, OutputStream out, byte[] c } } - public static void copyStreamToStream(InputStream in, OutputStream out, int copyBufferSize) + public static void copyStreamToStream(@Nonnull InputStream in, @Nonnull OutputStream out, int copyBufferSize) throws ReadException, WriteException { copyStreamToStream(in, out, new byte[copyBufferSize]); } - public static byte[] slurp(InputStream in, int byteLimit) throws IOException { + public static @Nonnull byte[] slurp(@Nonnull InputStream in, int byteLimit) throws IOException { return slurp(in, byteLimit, new byte[DEFAULT_COPY_BUFFER_SIZE]); } - public static byte[] slurp(InputStream in, int byteLimit, byte[] slurpBuffer) throws IOException { + public static @Nonnull byte[] slurp(@Nonnull InputStream in, int byteLimit, @Nonnull byte[] slurpBuffer) throws IOException { if (byteLimit < 0) throw new RuntimeException("'byteLimit' must be non-negative: " + byteLimit); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -80,11 +83,11 @@ public static byte[] slurp(InputStream in, int byteLimit, byte[] slurpBuffer) th return baos.toByteArray(); } - public void copyFileToStream(File fin, OutputStream out) throws ReadException, WriteException { + public void copyFileToStream(@Nonnull File fin, @Nonnull OutputStream out) throws ReadException, WriteException { copyFileToStream(fin, out, DEFAULT_COPY_BUFFER_SIZE); } - public void copyFileToStream(File fin, OutputStream out, int copyBufferSize) throws ReadException, WriteException { + public void copyFileToStream(@Nonnull File fin, @Nonnull OutputStream out, int copyBufferSize) throws ReadException, WriteException { FileInputStream in; try { in = new FileInputStream(fin); @@ -99,11 +102,11 @@ public void copyFileToStream(File fin, OutputStream out, int copyBufferSize) thr } } - public void copyStreamToFile(InputStream in, File fout) throws ReadException, WriteException { + public void copyStreamToFile(@Nonnull InputStream in, @Nonnull File fout) throws ReadException, WriteException { copyStreamToFile(in, fout, DEFAULT_COPY_BUFFER_SIZE); } - public void copyStreamToFile(InputStream in, File fout, int copyBufferSize) throws ReadException, WriteException { + public void copyStreamToFile(@Nonnull InputStream in, @Nonnull File fout, int copyBufferSize) throws ReadException, WriteException { FileOutputStream out; try { out = new FileOutputStream(fout); @@ -124,7 +127,7 @@ public void copyStreamToFile(InputStream in, File fout, int copyBufferSize) thro /** * Closes the given input stream and ignores the IOException. */ - public static void closeInput(InputStream in) { + public static void closeInput(@Nullable InputStream in) { try { if (in != null) { in.close(); @@ -137,7 +140,7 @@ public static void closeInput(InputStream in) { /** * Closes the given Reader and ignores the IOException. */ - public static void closeInput(Reader in) { + public static void closeInput(@Nullable Reader in) { try { if (in != null) { in.close(); @@ -147,7 +150,7 @@ public static void closeInput(Reader in) { } } - public static void closeQuietly(Closeable obj) { + public static void closeQuietly(@Nullable Closeable obj) { if (obj != null) { try { obj.close(); @@ -157,28 +160,28 @@ public static void closeQuietly(Closeable obj) { } } - public static InputStream limit(InputStream in, long limit) { + public static @Nonnull InputStream limit(@Nonnull InputStream in, long limit) { return new LimitInputStream(in, limit); } public static abstract class WrappedException extends IOException { private static final long serialVersionUID = 0; - public WrappedException(String message, IOException underlying) { + public WrappedException(@Nullable String message, @Nonnull IOException underlying) { super(message + ": " + underlying.getMessage(), underlying); } - public WrappedException(IOException underlying) { + public WrappedException(@Nonnull IOException underlying) { super(underlying); } @Override - public IOException getCause() { + public @Nonnull IOException getCause() { return (IOException) super.getCause(); } @Override - public String getMessage() { + public @Nonnull String getMessage() { String m = super.getCause().getMessage(); if (m == null) return ""; else return m; @@ -188,11 +191,11 @@ public String getMessage() { public static final class ReadException extends WrappedException { private static final long serialVersionUID = 0; - public ReadException(String message, IOException underlying) { + public ReadException(@Nullable String message, @Nonnull IOException underlying) { super(message, underlying); } - public ReadException(IOException underlying) { + public ReadException(@Nonnull IOException underlying) { super(underlying); } } @@ -200,25 +203,25 @@ public ReadException(IOException underlying) { public static final class WriteException extends WrappedException { private static final long serialVersionUID = 0; - public WriteException(String message, IOException underlying) { + public WriteException(@Nullable String message, @Nonnull IOException underlying) { super(message, underlying); } - public WriteException(IOException underlying) { + public WriteException(@Nonnull IOException underlying) { super(underlying); } } - public static final InputStream EmptyInputStream = new InputStream() { + public static final @Nonnull InputStream EmptyInputStream = new InputStream() { public int read() { return -1; } - public int read(byte[] data) { return -1; } - public int read(byte[] data, int off, int len) { return -1; } + public int read(@Nonnull byte[] data) { return -1; } + public int read(@Nonnull byte[] data, int off, int len) { return -1; } }; - public static final OutputStream BlackHoleOutputStream = new OutputStream() { + public static final @Nonnull OutputStream BlackHoleOutputStream = new OutputStream() { public void write(int b) {} - public void write(byte[] data) {} - public void write(byte[] data, int off, int len) {} + public void write(@Nonnull byte[] data) {} + public void write(@Nonnull byte[] data, int off, int len) {} }; /** @@ -228,7 +231,7 @@ public void write(byte[] data, int off, int len) {} private static final class LimitInputStream extends FilterInputStream { private long left; - public LimitInputStream(InputStream in, long limit) { + public LimitInputStream(@Nonnull InputStream in, long limit) { super(in); if (in == null) { diff --git a/core/src/main/java/com/dropbox/core/util/LangUtil.java b/core/src/main/java/com/dropbox/core/util/LangUtil.java index 9418f8567..20f2aebea 100644 --- a/core/src/main/java/com/dropbox/core/util/LangUtil.java +++ b/core/src/main/java/com/dropbox/core/util/LangUtil.java @@ -1,16 +1,16 @@ package com.dropbox.core.util; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; -/*>>> import checkers.nullness.quals.Nullable; */ -/*>>> import checkers.nullness.quals.NonNull; */ public class LangUtil { - public static RuntimeException mkAssert(String messagePrefix, Throwable cause) + public static @Nonnull RuntimeException mkAssert(@Nonnull String messagePrefix, @Nonnull Throwable cause) { RuntimeException ae = new RuntimeException(messagePrefix + ": " + cause.getMessage()); ae.initCause(cause); @@ -20,7 +20,7 @@ public static RuntimeException mkAssert(String messagePrefix, Throwable cause) // RuntimeException worked. } - public static AssertionError badType(Object a) + public static @Nonnull AssertionError badType(@Nullable Object a) { String msg; if (a == null) { @@ -31,30 +31,30 @@ public static AssertionError badType(Object a) return new AssertionError(msg); } - public static T[] arrayConcat(T[] a, T[] b) + public static @Nonnull T[] arrayConcat(@Nonnull T[] a, @Nonnull T[] b) { if (a == null) throw new IllegalArgumentException("'a' can't be null"); if (b == null) throw new IllegalArgumentException("'b' can't be null"); - /*@Nullable*/T[] rn = Arrays.copyOf(a, a.length + b.length); + @Nullable T[] rn = Arrays.copyOf(a, a.length + b.length); System.arraycopy(b, 0, rn, a.length, b.length); @SuppressWarnings("nullness") T[] r = rn; return r; } - public static boolean nullableEquals(/*@Nullable*/T a, /*@Nullable*/T b) + public static boolean nullableEquals(@Nullable T a, @Nullable T b) { if (a == null) return (b == null); if (b == null) return false; return a.equals(b); } - public static int nullableHashCode(/*@Nullable*/Object o) + public static int nullableHashCode(@Nullable Object o) { if (o == null) return 0; return o.hashCode() + 1; } - public static Date truncateMillis(/*@Nullable*/Date date) { + public static @Nullable Date truncateMillis(@Nullable Date date) { if (date != null) { long time = date.getTime(); return new Date(time - (time % 1000L)); @@ -63,7 +63,7 @@ public static Date truncateMillis(/*@Nullable*/Date date) { } } - public static List truncateMillis(/*@Nullable*/List dates) { + public static @Nullable List truncateMillis(@Nullable List dates) { if (dates != null) { List truncated = new ArrayList(dates.size()); for (Date date : dates) { diff --git a/core/src/main/java/com/dropbox/core/util/Maybe.java b/core/src/main/java/com/dropbox/core/util/Maybe.java index 3719d38dd..ba6a50dd2 100644 --- a/core/src/main/java/com/dropbox/core/util/Maybe.java +++ b/core/src/main/java/com/dropbox/core/util/Maybe.java @@ -1,39 +1,42 @@ package com.dropbox.core.util; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public abstract class Maybe { private Maybe() {} public abstract boolean isNothing(); public abstract boolean isJust(); - public abstract T getJust(); - public abstract T get(T def); - public abstract String toString(); + public abstract @Nullable T getJust(); + public abstract @Nullable T get(@Nullable T def); + public abstract @Nonnull String toString(); public abstract int hashCode(); - public abstract boolean equals(Maybe other); + public abstract boolean equals(@Nullable Maybe other); - public static Maybe Just(T value) + public static @Nonnull Maybe Just(@Nullable T value) { return new Just(value); } private static final class Just extends Maybe { - private final T value; - private Just(T value) + private final @Nullable T value; + private Just(@Nullable T value) { this.value = value; } public boolean isNothing() { return false; } public boolean isJust() { return true; } - public T getJust() { return value; } - public T get(T def) { return value; } - public String toString() { return "Just(" + value + ")"; } + public @Nullable T getJust() { return value; } + public @Nullable T get(@Nullable T def) { return value; } + public @Nonnull String toString() { return "Just(" + value + ")"; } public int hashCode() { return 1 + LangUtil.nullableHashCode(value); } @Override - public boolean equals(Maybe other) + public boolean equals(@Nullable Maybe other) { if (other instanceof Just) { Just j = (Just) other; @@ -49,25 +52,25 @@ else if (other instanceof Nothing) { } @SuppressWarnings("unchecked") - public static Maybe Nothing() + public static @Nonnull Maybe Nothing() { return (Maybe) Nothing; } - private static final Maybe Nothing = new Nothing(); + private static final @Nonnull Maybe Nothing = new Nothing(); private static final class Nothing extends Maybe { private Nothing() {} public boolean isNothing() { return true; } public boolean isJust() { return false; } - public T getJust() { throw new IllegalStateException("can't call getJust() on a Nothing"); } - public T get(T def) { return def; } - public String toString() { return "Nothing"; } + public @Nullable T getJust() { throw new IllegalStateException("can't call getJust() on a Nothing"); } + public @Nullable T get(@Nullable T def) { return def; } + public @Nonnull String toString() { return "Nothing"; } public int hashCode() { return 0; } @Override - public boolean equals(Maybe other) + public boolean equals(@Nullable Maybe other) { return other == this; // There's only a single Nothing instance. } diff --git a/core/src/main/java/com/dropbox/core/util/ProgressOutputStream.java b/core/src/main/java/com/dropbox/core/util/ProgressOutputStream.java index 860cf5a40..5aa20948d 100644 --- a/core/src/main/java/com/dropbox/core/util/ProgressOutputStream.java +++ b/core/src/main/java/com/dropbox/core/util/ProgressOutputStream.java @@ -3,33 +3,36 @@ import java.io.IOException; import java.io.OutputStream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public class ProgressOutputStream extends OutputStream { private long completed; - private OutputStream underlying; - private IOUtil.ProgressListener listener; + private @Nonnull OutputStream underlying; + private @Nullable IOUtil.ProgressListener listener; - public ProgressOutputStream(OutputStream underlying) { + public ProgressOutputStream(@Nonnull OutputStream underlying) { this.underlying = underlying; this.completed = 0; } - public ProgressOutputStream(OutputStream underlying, IOUtil.ProgressListener listener) { + public ProgressOutputStream(@Nonnull OutputStream underlying, @Nullable IOUtil.ProgressListener listener) { this(underlying); this.listener = listener; } - public void setListener(IOUtil.ProgressListener listener) { + public void setListener(@Nullable IOUtil.ProgressListener listener) { this.listener = listener; } @Override - public void write(byte[] data, int off, int len) throws IOException { + public void write(@Nonnull byte[] data, int off, int len) throws IOException { this.underlying.write(data, off, len); track(len); } @Override - public void write(byte[] data) throws IOException { + public void write(@Nonnull byte[] data) throws IOException { this.underlying.write(data); track(data.length); } diff --git a/core/src/main/java/com/dropbox/core/util/StringUtil.java b/core/src/main/java/com/dropbox/core/util/StringUtil.java index dce1e913d..4152b0774 100644 --- a/core/src/main/java/com/dropbox/core/util/StringUtil.java +++ b/core/src/main/java/com/dropbox/core/util/StringUtil.java @@ -11,20 +11,22 @@ import java.util.Arrays; import java.util.Collection; +import javax.annotation.Nonnull; + public class StringUtil { - public static final Charset UTF8 = Charset.forName("UTF-8"); + public static final @Nonnull Charset UTF8 = Charset.forName("UTF-8"); - private static final char[] HexDigits = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',}; + private static final @Nonnull char[] HexDigits = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',}; public static char hexDigit(int i) { return HexDigits[i]; } - public static String utf8ToString(byte[] utf8Data) + public static @Nonnull String utf8ToString(@Nonnull byte[] utf8Data) throws CharacterCodingException { return utf8ToString(utf8Data, 0, utf8Data.length); } - public static String utf8ToString(byte[] utf8Data, int offset, int length) + public static @Nonnull String utf8ToString(@Nonnull byte[] utf8Data, int offset, int length) throws CharacterCodingException { // NOTE: Using the String(..., UTF8) constructor would be wrong. That method will @@ -34,7 +36,7 @@ public static String utf8ToString(byte[] utf8Data, int offset, int length) return result.toString(); } - public static byte[] stringToUtf8(String s) + public static @Nonnull byte[] stringToUtf8(@Nonnull String s) { try { // Java 1.5 doesn't have the version of getBytes that takes a Charset object, so we @@ -50,7 +52,7 @@ public static byte[] stringToUtf8(String s) * Given a string, returns the representation of that string * as a Java string literal. */ - public static String javaQuotedLiteral(String value) + public static @Nonnull String javaQuotedLiteral(@Nonnull String value) { StringBuilder b = new StringBuilder(value.length() * 2); b.append('"'); @@ -84,11 +86,11 @@ public static String javaQuotedLiteral(String value) return b.toString(); } - public static String javaQuotedLiterals(String[] value) { + public static @Nonnull String javaQuotedLiterals(@Nonnull String[] value) { return javaQuotedLiterals(Arrays.asList(value)); } - public static String javaQuotedLiterals(Iterable value) { + public static @Nonnull String javaQuotedLiterals(@Nonnull Iterable value) { StringBuilder b = new StringBuilder(); String sep = ""; for (String element : value) { @@ -100,13 +102,13 @@ public static String javaQuotedLiterals(Iterable value) { } /** Shorthand for {@link #javaQuotedLiteral}. */ - public static String jq(String value) { return javaQuotedLiteral(value); } + public static @Nonnull String jq(@Nonnull String value) { return javaQuotedLiteral(value); } /** Shorthand for {@link #javaQuotedLiterals}. */ - public static String jq(String[] value) { return javaQuotedLiterals(value); } + public static @Nonnull String jq(@Nonnull String[] value) { return javaQuotedLiterals(value); } /** Shorthand for {@link #javaQuotedLiterals}. */ - public static String jq(Iterable value) { return javaQuotedLiterals(value); } + public static @Nonnull String jq(@Nonnull Iterable value) { return javaQuotedLiterals(value); } - public static String binaryToHex(byte[] data) + public static @Nonnull String binaryToHex(@Nonnull byte[] data) { return binaryToHex(data, 0, data.length); } @@ -116,7 +118,7 @@ public static String binaryToHex(byte[] data) * The resulting String will have two characters for every byte in the * input. */ - public static String binaryToHex(byte[] data, int offset, int length) + public static @Nonnull String binaryToHex(@Nonnull byte[] data, int offset, int length) { assert offset < data.length && offset >= 0 : offset + ", " + data.length; int end = offset + length; @@ -139,7 +141,7 @@ public static String binaryToHex(byte[] data, int offset, int length) * this function to check for equality. Using regular {@code String.equals} is not * secure. */ - public static boolean secureStringEquals(String a, String b) + public static boolean secureStringEquals(@Nonnull String a, @Nonnull String b) { if (a.length() != b.length()) return false; @@ -154,24 +156,24 @@ public static boolean secureStringEquals(String a, String b) return result == 0; } - public static final String Base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - public static final String UrlSafeBase64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + public static final @Nonnull String Base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + public static final @Nonnull String UrlSafeBase64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; static { assert Base64Digits.length() == 64 : Base64Digits.length(); assert UrlSafeBase64Digits.length() == 64 : UrlSafeBase64Digits.length(); } - public static String base64Encode(byte[] data) + public static @Nonnull String base64Encode(@Nonnull byte[] data) { return base64EncodeGeneric(Base64Digits, data); } - public static String urlSafeBase64Encode(byte[] data) + public static @Nonnull String urlSafeBase64Encode(@Nonnull byte[] data) { return base64EncodeGeneric(UrlSafeBase64Digits, data); } - public static String base64EncodeGeneric(String digits, byte[] data) + public static @Nonnull String base64EncodeGeneric(@Nonnull String digits, @Nonnull byte[] data) { if (data == null) throw new IllegalArgumentException("'data' can't be null"); if (digits == null) throw new IllegalArgumentException("'digits' can't be null"); @@ -234,7 +236,7 @@ else if (remaining == 2) { return buf.toString(); } - public static String join(Collection strings, String delimiter) { + public static @Nonnull String join(@Nonnull Collection strings, @Nonnull String delimiter) { StringBuilder sb = new StringBuilder(); int i = 0; for (String s: strings) { diff --git a/core/src/main/java/com/dropbox/core/v1/DbxAccountInfo.java b/core/src/main/java/com/dropbox/core/v1/DbxAccountInfo.java index d9563d5d4..dce6ba2fe 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxAccountInfo.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxAccountInfo.java @@ -11,20 +11,23 @@ import java.io.IOException; +import javax.annotation.Nonnull; + public class DbxAccountInfo extends Dumpable { public final long userId; - public final String displayName; - public final String country; - public final String referralLink; - public final Quota quota; - public final String email; - public final NameDetails nameDetails; + public final @Nonnull String displayName; + public final @Nonnull String country; + public final @Nonnull String referralLink; + public final @Nonnull Quota quota; + public final @Nonnull String email; + public final @Nonnull NameDetails nameDetails; public final boolean emailVerified; - public DbxAccountInfo(long userId, String displayName, String country, String referralLink, Quota quota, String email, - NameDetails nameDetails, boolean emailVerified) + public DbxAccountInfo(long userId, @Nonnull String displayName, @Nonnull String country, + @Nonnull String referralLink, @Nonnull Quota quota, @Nonnull String email, + @Nonnull NameDetails nameDetails, boolean emailVerified) { this.userId = userId; this.displayName = displayName; @@ -37,7 +40,7 @@ public DbxAccountInfo(long userId, String displayName, String country, String re } @Override - protected void dumpFields(DumpWriter out) + protected void dumpFields(@Nonnull DumpWriter out) { out.f("userId").v(userId); out.f("displayName").v(displayName); @@ -63,7 +66,7 @@ public Quota(long quota, long normal, long quotaShared) } @Override - protected void dumpFields(DumpWriter out) + protected void dumpFields(@Nonnull DumpWriter out) { out.f("total").v(total); out.f("normal").v(normal); @@ -73,9 +76,9 @@ protected void dumpFields(DumpWriter out) // ------------------------------------------------------ // JSON parsing - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { - public final Quota read(JsonParser parser) + public final @Nonnull Quota read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -131,11 +134,11 @@ public final Quota read(JsonParser parser) public static final class NameDetails extends Dumpable { - public final String familiarName; - public final String givenName; - public final String surname; + public final @Nonnull String familiarName; + public final @Nonnull String givenName; + public final @Nonnull String surname; - public NameDetails(String familiarName, String givenName, String surname) + public NameDetails(@Nonnull String familiarName, @Nonnull String givenName, @Nonnull String surname) { this.familiarName = familiarName; this.givenName = givenName; @@ -143,7 +146,7 @@ public NameDetails(String familiarName, String givenName, String surname) } @Override - protected void dumpFields(DumpWriter out) + protected void dumpFields(@Nonnull DumpWriter out) { out.f("familiarName").v(familiarName); out.f("givenName").v(givenName); @@ -153,9 +156,9 @@ protected void dumpFields(DumpWriter out) // ------------------------------------------------------ // JSON parsing - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { - public final NameDetails read(JsonParser parser) + public final @Nonnull NameDetails read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -212,9 +215,9 @@ public final NameDetails read(JsonParser parser) // ------------------------------------------------------ // JSON parsing - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { - public final DbxAccountInfo read(JsonParser parser) + public final @Nonnull DbxAccountInfo read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); diff --git a/core/src/main/java/com/dropbox/core/v1/DbxClientV1.java b/core/src/main/java/com/dropbox/core/v1/DbxClientV1.java index 3911291ef..986187f7a 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxClientV1.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxClientV1.java @@ -1,5 +1,7 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -20,10 +22,6 @@ import static com.dropbox.core.util.StringUtil.jq; -/*>>> import checkers.nullness.quals.NonNull; */ -/*>>> import checkers.nullness.quals.Nullable; */ -/*>>> import checkers.nullness.quals.MonotonicNonNull; */ -/*>>> import checkers.initialization.quals.Initialized; */ /** * Use this class to make remote calls to the Dropbox API. You'll need an access token first, @@ -36,11 +34,11 @@ */ public final class DbxClientV1 { - public static final String USER_AGENT_ID = "Dropbox-Java-SDK"; + public static final @Nonnull String USER_AGENT_ID = "Dropbox-Java-SDK"; - private final DbxRequestConfig requestConfig; - private final String accessToken; - private final DbxHost host; + private final @Nonnull DbxRequestConfig requestConfig; + private final @Nonnull String accessToken; + private final @Nonnull DbxHost host; /** * @param accessToken @@ -49,7 +47,7 @@ public final class DbxClientV1 * to get one of these is to use {@link DbxWebAuth} to send your user through Dropbox's * OAuth 2 authorization flow. */ - public DbxClientV1(DbxRequestConfig requestConfig, String accessToken) + public DbxClientV1(@Nonnull DbxRequestConfig requestConfig, @Nonnull String accessToken) { this(requestConfig, accessToken, DbxHost.DEFAULT); } @@ -59,7 +57,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken) * hostnames of the Dropbox API servers. This is used in testing. You don't normally need * to call this. */ - public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost host) + public DbxClientV1(@Nonnull DbxRequestConfig requestConfig, @Nonnull String accessToken, @Nonnull DbxHost host) { if (requestConfig == null) throw new IllegalArgumentException("'requestConfig' is null"); if (accessToken == null) throw new IllegalArgumentException("'accessToken' is null"); @@ -73,17 +71,17 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h /** * Returns the {@code DbxRequestConfig} that was passed in to the constructor. */ - public DbxRequestConfig getRequestConfig() { return requestConfig; } + public @Nonnull DbxRequestConfig getRequestConfig() { return requestConfig; } /** * Returns the {@code DbxAccessToken} that was passed in to the constructor. */ - public String getAccessToken() { return accessToken; } + public @Nonnull String getAccessToken() { return accessToken; } /** * Returns the {@code DbxHost} that was passed in to the constructor. */ - public DbxHost getHost() { return host; } + public @Nonnull DbxHost getHost() { return host; } // ----------------------------------------------------------------- // /metadata @@ -112,21 +110,21 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * metadata for that path. If there is no file or folder there, * return {@code null}. */ - public /*@Nullable*/DbxEntry getMetadata(final String path, boolean includeMediaInfo) + public @Nullable DbxEntry getMetadata(final @Nonnull String path, boolean includeMediaInfo) throws DbxException { DbxPathV1.checkArg("path", path); String host = this.host.getApi(); String apiPath = "1/metadata/auto" + path; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "list", "false", "include_media_info", includeMediaInfo ? "true" : null, }; - return doGet(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler() { + return doGet(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/DbxEntry handle(HttpRequestor.Response response) throws DbxException + public @Nullable DbxEntry handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 404) return null; if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); @@ -140,7 +138,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * Same as {@link #getMetadata(String, boolean)} with {@code includeMediaInfo} set * to {@code false}. */ - public /*@Nullable*/DbxEntry getMetadata(final String path) + public @Nullable DbxEntry getMetadata(final @Nonnull String path) throws DbxException { return getMetadata(path, false); @@ -171,7 +169,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * Otherwise, return the metadata for that path and the metadata for all its immediate * children (if it's a folder). */ - public DbxEntry./*@Nullable*/WithChildren getMetadataWithChildren(String path, boolean includeMediaInfo) + public @Nullable DbxEntry.WithChildren getMetadataWithChildren(@Nonnull String path, boolean includeMediaInfo) throws DbxException { return getMetadataWithChildrenBase(path, includeMediaInfo, DbxEntry.WithChildren.ReaderMaybeDeleted); @@ -181,7 +179,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * Same as {@link #getMetadataWithChildren(String, boolean)} with {@code includeMediaInfo} set * to {@code false}. */ - public DbxEntry./*@Nullable*/WithChildren getMetadataWithChildren(String path) + public @Nullable DbxEntry.WithChildren getMetadataWithChildren(@Nonnull String path) throws DbxException { return getMetadataWithChildren(path, false); @@ -201,7 +199,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * the entire call succeeds. *

*/ - public DbxEntry./*@Nullable*/WithChildrenC getMetadataWithChildrenC(String path, boolean includeMediaInfo, final Collector collector) + public @Nullable DbxEntry.WithChildrenC getMetadataWithChildrenC(@Nonnull String path, boolean includeMediaInfo, final @Nonnull Collector collector) throws DbxException { return getMetadataWithChildrenBase(path, includeMediaInfo, new DbxEntry.WithChildrenC.ReaderMaybeDeleted(collector)); @@ -211,13 +209,13 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * Same as {@link #getMetadataWithChildrenC(String, boolean, Collector)} with {@code includeMediaInfo} set * to {@code false}. */ - public DbxEntry./*@Nullable*/WithChildrenC getMetadataWithChildrenC(String path, final Collector collector) + public @Nullable DbxEntry.WithChildrenC getMetadataWithChildrenC(@Nonnull String path, final @Nonnull Collector collector) throws DbxException { return getMetadataWithChildrenC(path, false, collector); } - private /*@Nullable*/T getMetadataWithChildrenBase(String path, boolean includeMediaInfo, final JsonReader reader) + private @Nullable T getMetadataWithChildrenBase(String path, boolean includeMediaInfo, final JsonReader reader) throws DbxException { DbxPathV1.checkArg("path", path); @@ -225,15 +223,15 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h String host = this.host.getApi(); String apiPath = "1/metadata/auto" + path; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "list", "true", "file_limit", "25000", "include_media_info", includeMediaInfo ? "true" : null, }; - return doGet(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler() { + return doGet(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/T handle(HttpRequestor.Response response) throws DbxException + public @Nullable T handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 404) return null; if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); @@ -261,7 +259,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * {@code Maybe.Just(null)} if there's nothing there or {@code Maybe.Just} with the * metadata. */ - public Maybe getMetadataWithChildrenIfChanged(String path, boolean includeMediaInfo, /*@Nullable*/String previousFolderHash) + public @Nonnull Maybe getMetadataWithChildrenIfChanged(@Nonnull String path, boolean includeMediaInfo, @Nonnull String previousFolderHash) throws DbxException { return getMetadataWithChildrenIfChangedBase(path, includeMediaInfo, previousFolderHash, DbxEntry.WithChildren.ReaderMaybeDeleted); @@ -271,7 +269,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * Same as {@link #getMetadataWithChildrenIfChanged(String, boolean, String)} with {@code includeMediaInfo} set * to {@code false}. */ - public Maybe getMetadataWithChildrenIfChanged(String path, /*@Nullable*/String previousFolderHash) + public @Nonnull Maybe getMetadataWithChildrenIfChanged(@Nonnull String path, @Nonnull String previousFolderHash) throws DbxException { return getMetadataWithChildrenIfChanged(path, false, previousFolderHash); @@ -291,8 +289,8 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * the entire call succeeds. *

*/ - public Maybe> getMetadataWithChildrenIfChangedC( - String path, boolean includeMediaInfo, /*@Nullable*/String previousFolderHash, Collector collector) + public Maybe> getMetadataWithChildrenIfChangedC( + @Nonnull String path, boolean includeMediaInfo, @Nonnull String previousFolderHash, @Nonnull Collector collector) throws DbxException { return getMetadataWithChildrenIfChangedBase(path, includeMediaInfo, previousFolderHash, new DbxEntry.WithChildrenC.ReaderMaybeDeleted(collector)); @@ -302,15 +300,15 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h * Same as {@link #getMetadataWithChildrenIfChangedC(String, boolean, String, Collector)} with * {@code includeMediaInfo} set to {@code false}. */ - public Maybe> getMetadataWithChildrenIfChangedC( - String path, /*@Nullable*/String previousFolderHash, Collector collector) + public Maybe> getMetadataWithChildrenIfChangedC( + @Nonnull String path, @Nonnull String previousFolderHash, @Nonnull Collector collector) throws DbxException { return getMetadataWithChildrenIfChangedC(path, false, previousFolderHash, collector); } - private Maybe getMetadataWithChildrenIfChangedBase( - String path, boolean includeMediaInfo, /*@Nullable*/String previousFolderHash, final JsonReader reader) + private Maybe getMetadataWithChildrenIfChangedBase( + String path, boolean includeMediaInfo, @Nullable String previousFolderHash, final JsonReader reader) throws DbxException { if (previousFolderHash == null) throw new IllegalArgumentException("'previousFolderHash' must not be null"); @@ -320,22 +318,22 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h String host = this.host.getApi(); String apiPath = "1/metadata/auto" + path; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "list", "true", "file_limit", "25000", "hash", previousFolderHash, "include_media_info", includeMediaInfo ? "true" : null, }; - return doGet(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler>() { + return doGet(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler>() { @Override - public Maybe handle(HttpRequestor.Response response) throws DbxException + public @Nonnull Maybe handle(@Nonnull HttpRequestor.Response response) throws DbxException { - if (response.getStatusCode() == 404) return Maybe.Just(null); - if (response.getStatusCode() == 304) return Maybe.Nothing(); + if (response.getStatusCode() == 404) return Maybe.Just(null); + if (response.getStatusCode() == 304) return Maybe.Nothing(); if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); - return Maybe.Just(DbxRequestUtil.readJsonFromResponse(reader, response)); + return Maybe.Just(DbxRequestUtil.readJsonFromResponse(reader, response)); } }); } @@ -346,7 +344,7 @@ public DbxClientV1(DbxRequestConfig requestConfig, String accessToken, DbxHost h /** * Retrieve the user's account information. */ - public DbxAccountInfo getAccountInfo() + public @Nonnull DbxAccountInfo getAccountInfo() throws DbxException { String host = this.host.getApi(); @@ -354,7 +352,7 @@ public DbxAccountInfo getAccountInfo() return doGet(host, apiPath, null, null, new DbxRequestUtil.ResponseHandler() { @Override - public DbxAccountInfo handle(HttpRequestor.Response response) throws DbxException + public @Nonnull DbxAccountInfo handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); @@ -377,9 +375,9 @@ public void disableAccessToken() String host = this.host.getApi(); String apiPath = "1/disable_access_token"; - doPost(host, apiPath, null, null, new DbxRequestUtil.ResponseHandler() { + doPost(host, apiPath, null, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/Void handle(HttpRequestor.Response response) throws DbxException + public @Nullable Void handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) { String requestId = DbxRequestUtil.getRequestId(response); @@ -419,7 +417,7 @@ public void disableAccessToken() * @throws IOException * If there's an error writing to {@code target}. */ - public DbxEntry./*@Nullable*/File getFile(String path, /*@Nullable*/String rev, OutputStream target) + public @Nullable DbxEntry.File getFile(@Nonnull String path, @Nullable String rev, @Nonnull OutputStream target) throws DbxException, IOException { Downloader downloader = startGetFile(path, rev); @@ -454,12 +452,12 @@ public void disableAccessToken() * An object that can be used to download the file contents, or * {@code null} if there is no file at the requested path. */ - public /*@Nullable*/Downloader startGetFile(final String path, /*@Nullable*/String rev) + public @Nullable Downloader startGetFile(final @Nonnull String path, @Nullable String rev) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); String apiPath = "1/files/auto" + path; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "rev", rev }; return startGetSomething(apiPath, params); @@ -468,8 +466,8 @@ public void disableAccessToken() /** * Generic function that downloads either files or thumbnails. */ - private /*@Nullable*/Downloader startGetSomething(final String apiPath, - final /*@Nullable*/String[] params) + private @Nullable Downloader startGetSomething(final String apiPath, + final @Nullable String[] params) throws DbxException { final String host = this.host.getContent(); @@ -479,7 +477,7 @@ public void disableAccessToken() return DbxRequestUtil.runAndRetry(requestConfig.getMaxRetries(), new DbxRequestUtil.RequestMaker() { @Override - public Downloader run() throws DbxException { + public @Nullable Downloader run() throws DbxException { HttpRequestor.Response response = DbxRequestUtil.startGet(requestConfig, accessToken, USER_AGENT_ID, host, apiPath, params, null); boolean passedOwnershipOfStream = false; @@ -525,10 +523,10 @@ public Downloader run() throws DbxException { */ public static final class Downloader { - public final DbxEntry.File metadata; - public final InputStream body; + public final @Nonnull DbxEntry.File metadata; + public final @Nonnull InputStream body; - public Downloader(DbxEntry.File metadata, InputStream body) + public Downloader(@Nonnull DbxEntry.File metadata, @Nonnull InputStream body) { this.metadata = metadata; this.body = body; @@ -538,7 +536,7 @@ public Downloader(DbxEntry.File metadata, InputStream body) * Copies all of {@code #body} to the given output stream. As a convenience, also * returns {@code #metadata}. */ - DbxEntry.File copyBodyAndClose(OutputStream target) + @Nonnull DbxEntry.File copyBodyAndClose(@Nonnull OutputStream target) throws DbxException, IOException { try { @@ -597,7 +595,7 @@ public void close() * @throws IOException * If there's an error reading from {@code in}. */ - public DbxEntry.File uploadFile(String targetPath, DbxWriteMode writeMode, long numBytes, InputStream contents) + public @Nonnull DbxEntry.File uploadFile(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes, @Nonnull InputStream contents) throws DbxException, IOException { return uploadFile(targetPath, writeMode, numBytes, new DbxStreamWriter.InputStreamCopier(contents)); @@ -644,7 +642,7 @@ public DbxEntry.File uploadFile(String targetPath, DbxWriteMode writeMode, long * @throws E * If {@code writer.write()} throws an exception, it will propagate out of this function. */ - public DbxEntry.File uploadFile(String targetPath, DbxWriteMode writeMode, long numBytes, DbxStreamWriter writer) + public @Nonnull DbxEntry.File uploadFile(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes, @Nonnull DbxStreamWriter writer) throws DbxException, E { Uploader uploader = startUploadFile(targetPath, writeMode, numBytes); @@ -689,7 +687,7 @@ public DbxEntry.File uploadFile(String targetPath, DbxWrit * The number of bytes you're going to upload via the returned {@link DbxClientV1.Uploader}. * Use {@code -1} if you don't know ahead of time. */ - public Uploader startUploadFile(String targetPath, DbxWriteMode writeMode, long numBytes) + public @Nonnull Uploader startUploadFile(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes) throws DbxException { if (numBytes < 0) { @@ -709,7 +707,7 @@ else if (numBytes > ChunkedUploadThreshold) { } } - public DbxEntry.File finishUploadFile(Uploader uploader, DbxStreamWriter writer) + public @Nonnull DbxEntry.File finishUploadFile(@Nonnull Uploader uploader, @Nonnull DbxStreamWriter writer) throws DbxException, E { NoThrowOutputStream streamWrapper = new NoThrowOutputStream(uploader.getBody()); @@ -733,7 +731,7 @@ public DbxEntry.File finishUploadFile(Uploader uploader, D * Similar to {@link #uploadFile}, except always uses the /files_put API call. * One difference is that {@code numBytes} must not be negative. */ - public Uploader startUploadFileSingle(String targetPath, DbxWriteMode writeMode, long numBytes) + public @Nonnull Uploader startUploadFileSingle(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes) throws DbxException { DbxPathV1.checkArg("targetPath", targetPath); @@ -751,7 +749,7 @@ public Uploader startUploadFileSingle(String targetPath, DbxWriteMode writeMode, return new SingleUploader(uploader, numBytes); } - public DbxEntry.File uploadFileSingle(String targetPath, DbxWriteMode writeMode, long numBytes, DbxStreamWriter writer) + public @Nonnull DbxEntry.File uploadFileSingle(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes, @Nonnull DbxStreamWriter writer) throws DbxException, E { Uploader uploader = startUploadFileSingle(targetPath, writeMode, numBytes); @@ -760,11 +758,11 @@ public DbxEntry.File uploadFileSingle(String targetPath, D private static final class SingleUploader extends Uploader { - private HttpRequestor./*@Nullable*/Uploader httpUploader; + private @Nullable HttpRequestor.Uploader httpUploader; private final long claimedBytes; private final CountingOutputStream body; - public SingleUploader(HttpRequestor.Uploader httpUploader, long claimedBytes) + public SingleUploader(@Nonnull HttpRequestor.Uploader httpUploader, long claimedBytes) { if (claimedBytes < 0) { throw new IllegalArgumentException("'numBytes' must be greater than or equal to 0"); @@ -775,7 +773,7 @@ public SingleUploader(HttpRequestor.Uploader httpUploader, long claimedBytes) this.body = new CountingOutputStream(httpUploader.getBody()); } - public OutputStream getBody() + public @Nonnull OutputStream getBody() { return this.body; } @@ -812,7 +810,7 @@ public void close() * to indicate that you're done. This will actually finish the underlying HTTP * request and return the uploaded file's {@link DbxEntry}. */ - public DbxEntry.File finish() + public @Nonnull DbxEntry.File finish() throws DbxException { if (httpUploader == null) { @@ -843,11 +841,11 @@ public DbxEntry.File finish() } @SuppressWarnings("nullness") // Workaround for bug in Checker Framework: https://code.google.com/p/checker-framework/issues/detail?id=293 - final HttpRequestor./*@Initialized*//*@NonNull*/Response nonNullResponse = response; + final HttpRequestor.Response nonNullResponse = response; return DbxRequestUtil.finishResponse(nonNullResponse, new DbxRequestUtil.ResponseHandler() { @Override - public DbxEntry.File handle(HttpRequestor.Response response) throws DbxException + public @Nonnull DbxEntry.File handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); DbxEntry.File f = DbxRequestUtil.readJsonFromResponse(DbxEntry.File.Reader, response); @@ -867,10 +865,10 @@ public DbxEntry.File handle(HttpRequestor.Response response) throws DbxException private static final class ChunkedUploadState extends Dumpable { - public final String uploadId; + public final @Nonnull String uploadId; public final long offset; - public ChunkedUploadState(String uploadId, long offset) + public ChunkedUploadState(@Nonnull String uploadId, long offset) { if (uploadId == null) throw new IllegalArgumentException("'uploadId' can't be null"); if (uploadId.length() == 0) throw new IllegalArgumentException("'uploadId' can't be empty"); @@ -879,16 +877,16 @@ public ChunkedUploadState(String uploadId, long offset) this.offset = offset; } - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { w.f("uploadId").v(uploadId); w.f("offset").v(offset); } - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public ChunkedUploadState read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull ChunkedUploadState read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -927,7 +925,7 @@ else if (fieldName.equals("offset")) { /** * Internal function called by both chunkedUploadFirst and chunkedUploadAppend. */ - private HttpRequestor.Response chunkedUploadCommon(String[] params, long chunkSize, DbxStreamWriter writer) + private @Nonnull HttpRequestor.Response chunkedUploadCommon(@Nonnull String[] params, long chunkSize, @Nonnull DbxStreamWriter writer) throws DbxException, E { String apiPath = "1/chunked_upload"; @@ -967,7 +965,7 @@ private HttpRequestor.Response chunkedUploadCommon(String[ } } - private /*@Nullable*/ChunkedUploadState chunkedUploadCheckForOffsetCorrection(HttpRequestor.Response response) + private @Nullable ChunkedUploadState chunkedUploadCheckForOffsetCorrection(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 400) return null; @@ -984,7 +982,7 @@ private HttpRequestor.Response chunkedUploadCommon(String[ } } - private ChunkedUploadState chunkedUploadParse200(HttpRequestor.Response response) + private @Nonnull ChunkedUploadState chunkedUploadParse200(@Nonnull HttpRequestor.Response response) throws BadResponseException, NetworkIOException { assert response.getStatusCode() == 200 : response.getStatusCode(); @@ -995,7 +993,7 @@ private ChunkedUploadState chunkedUploadParse200(HttpRequestor.Response response * Equivalent to {@link #chunkedUploadFirst(byte[], int, int) * chunkedUploadFirst(data, 0, data.length)}. */ - public String chunkedUploadFirst(byte[] data) + public @Nonnull String chunkedUploadFirst(@Nonnull byte[] data) throws DbxException { return chunkedUploadFirst(data, 0, data.length); @@ -1014,7 +1012,7 @@ public String chunkedUploadFirst(byte[] data) * @return * The ID designated by the Dropbox server to identify the chunked upload. */ - public String chunkedUploadFirst(byte[] data, int dataOffset, int dataLength) + public @Nonnull String chunkedUploadFirst(@Nonnull byte[] data, int dataOffset, int dataLength) throws DbxException { return chunkedUploadFirst(dataLength, new DbxStreamWriter.ByteArrayCopier(data, dataOffset, dataLength)); @@ -1033,7 +1031,7 @@ public String chunkedUploadFirst(byte[] data, int dataOffset, int dataLength) * @return * The ID designated by the Dropbox server to identify the chunked upload. */ - public String chunkedUploadFirst(int chunkSize, DbxStreamWriter writer) + public @Nonnull String chunkedUploadFirst(int chunkSize, @Nonnull DbxStreamWriter writer) throws DbxException, E { HttpRequestor.Response response = chunkedUploadCommon(new String[0], chunkSize, writer); @@ -1068,7 +1066,7 @@ public String chunkedUploadFirst(int chunkSize, DbxStreamW * Equivalent to {@link #chunkedUploadAppend(String, long, byte[], int, int) * chunkedUploadAppend(uploadId, uploadOffset, data, 0, data.length)}. */ - public long chunkedUploadAppend(String uploadId, long uploadOffset, byte[] data) + public long chunkedUploadAppend(@Nonnull String uploadId, long uploadOffset, @Nonnull byte[] data) throws DbxException { return chunkedUploadAppend(uploadId, uploadOffset, data, 0, data.length); @@ -1100,7 +1098,7 @@ public long chunkedUploadAppend(String uploadId, long uploadOffset, byte[] data) * match the actual number of bytes in the chunked upload session, returns the correct * number of bytes. */ - public long chunkedUploadAppend(String uploadId, long uploadOffset, byte[] data, int dataOffset, int dataLength) + public long chunkedUploadAppend(@Nonnull String uploadId, long uploadOffset, @Nonnull byte[] data, int dataOffset, int dataLength) throws DbxException { return chunkedUploadAppend(uploadId, uploadOffset, dataLength, new DbxStreamWriter.ByteArrayCopier(data, dataOffset, dataLength)); @@ -1130,7 +1128,7 @@ public long chunkedUploadAppend(String uploadId, long uploadOffset, byte[] data, * match the actual number of bytes in the chunked upload session, returns the correct * number of bytes. */ - public long chunkedUploadAppend(String uploadId, long uploadOffset, long chunkSize, DbxStreamWriter writer) + public long chunkedUploadAppend(@Nonnull String uploadId, long uploadOffset, long chunkSize, @Nonnull DbxStreamWriter writer) throws DbxException, E { if (uploadId == null) throw new IllegalArgumentException("'uploadId' can't be null"); @@ -1202,7 +1200,7 @@ public long chunkedUploadAppend(String uploadId, long uplo * @param uploadId * The identifier returned by {@link #chunkedUploadFirst} to identify the uploaded data. */ - public DbxEntry.File chunkedUploadFinish(String targetPath, DbxWriteMode writeMode, String uploadId) + public @Nonnull DbxEntry.File chunkedUploadFinish(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, @Nonnull String uploadId) throws DbxException { DbxPathV1.checkArgNonRoot("targetPath", targetPath); @@ -1216,7 +1214,7 @@ public DbxEntry.File chunkedUploadFinish(String targetPath, DbxWriteMode writeMo return doPost(host.getContent(), apiPath, params, null, new DbxRequestUtil.ResponseHandler() { @Override - public DbxEntry.File handle(HttpRequestor.Response response) throws DbxException + public @Nonnull DbxEntry.File handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); return DbxRequestUtil.readJsonFromResponse(DbxEntry.File.Reader, response); @@ -1227,7 +1225,7 @@ public DbxEntry.File handle(HttpRequestor.Response response) throws DbxException /** * Similar to {@link #startUploadFile}, except always uses the chunked upload API. */ - public Uploader startUploadFileChunked(String targetPath, DbxWriteMode writeMode, long numBytes) + public @Nonnull Uploader startUploadFileChunked(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes) { return startUploadFileChunked(ChunkedUploadChunkSize, targetPath, writeMode, numBytes); } @@ -1235,7 +1233,7 @@ public Uploader startUploadFileChunked(String targetPath, DbxWriteMode writeMode /** * Similar to {@link #startUploadFile}, except always uses the chunked upload API. */ - public Uploader startUploadFileChunked(int chunkSize, String targetPath, DbxWriteMode writeMode, long numBytes) + public @Nonnull Uploader startUploadFileChunked(int chunkSize, @Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes) { DbxPathV1.checkArg("targetPath", targetPath); if (writeMode == null) throw new IllegalArgumentException("'writeMode' can't be null"); @@ -1246,7 +1244,7 @@ public Uploader startUploadFileChunked(int chunkSize, String targetPath, DbxWrit /** * Similar to {@link #uploadFile}, except always uses the chunked upload API. */ - public DbxEntry.File uploadFileChunked(String targetPath, DbxWriteMode writeMode, long numBytes, DbxStreamWriter writer) + public @Nonnull DbxEntry.File uploadFileChunked(@Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes, @Nonnull DbxStreamWriter writer) throws DbxException, E { Uploader uploader = startUploadFileChunked(targetPath, writeMode, numBytes); @@ -1256,7 +1254,7 @@ public DbxEntry.File uploadFileChunked(String targetPath, /** * Similar to {@link #uploadFile}, except always uses the chunked upload API. */ - public DbxEntry.File uploadFileChunked(int chunkSize, String targetPath, DbxWriteMode writeMode, long numBytes, DbxStreamWriter writer) + public @Nonnull DbxEntry.File uploadFileChunked(int chunkSize, @Nonnull String targetPath, @Nonnull DbxWriteMode writeMode, long numBytes, @Nonnull DbxStreamWriter writer) throws DbxException, E { Uploader uploader = startUploadFileChunked(chunkSize, targetPath, writeMode, numBytes); @@ -1279,7 +1277,7 @@ private ChunkedUploader(String targetPath, DbxWriteMode writeMode, long numBytes } @Override - public OutputStream getBody() + public @Nonnull OutputStream getBody() { return body; } @@ -1291,7 +1289,7 @@ public void abort() } @Override - public DbxEntry.File finish() + public @Nonnull DbxEntry.File finish() throws DbxException { if (body.uploadId == null) { @@ -1315,7 +1313,7 @@ public DbxEntry.File finish() // to uploads, according to documentation, and (2) auto-retry is off by default, // which would break backwards compatibility here. return DbxRequestUtil.runAndRetry(3, new DbxRequestUtil.RequestMaker() { - public DbxEntry.File run() throws DbxException { + public @Nonnull DbxEntry.File run() throws DbxException { return chunkedUploadFinish(targetPath, writeMode, uploadId); } }); @@ -1333,7 +1331,7 @@ private final class ChunkedUploadOutputStream extends OutputStream { private final byte[] chunk; private int chunkPos = 0; - private /*@MonotonicNonNull*/String uploadId; + private @Nullable String uploadId; private long uploadOffset; private ChunkedUploadOutputStream(int chunkSize) @@ -1374,7 +1372,7 @@ private void finishChunk() // to uploads, according to documentation, and (2) auto-retry is off by default, // which would break backwards compatibility here. uploadId = DbxRequestUtil.runAndRetry(3, new DbxRequestUtil.RequestMaker() { - public String run() throws DbxException { + public @Nonnull String run() throws DbxException { return chunkedUploadFirst(chunk, 0, chunkPos); } }); @@ -1386,7 +1384,7 @@ public String run() throws DbxException { final int arrayOffsetFinal = arrayOffset; // don't use requestConfig.getMaxRetries() (see comment above) long correctedOffset = DbxRequestUtil.runAndRetry(3, new DbxRequestUtil.RequestMaker() { - public Long run() throws DbxException { + public @Nonnull Long run() throws DbxException { return chunkedUploadAppend(uploadId, uploadOffset, chunk, arrayOffsetFinal, chunkPos-arrayOffsetFinal); } }); @@ -1442,9 +1440,9 @@ public void close() public static final class IODbxException extends IOException { private static final long serialVersionUID = 0L; - public final DbxException underlying; + public final @Nonnull DbxException underlying; - public IODbxException(DbxException underlying) + public IODbxException(@Nonnull DbxException underlying) { super(underlying); this.underlying = underlying; @@ -1476,7 +1474,7 @@ public IODbxException(DbxException underlying) * for the App Folder's contents. *

*/ - public DbxDelta getDelta(/*@Nullable*/String cursor, boolean includeMediaInfo) + public @Nonnull DbxDelta getDelta(@Nullable String cursor, boolean includeMediaInfo) throws DbxException { return _getDelta(cursor, null, includeMediaInfo); @@ -1485,7 +1483,7 @@ public DbxDelta getDelta(/*@Nullable*/String cursor, boolean includeMe /** * Same as {@link #getDelta(String, boolean)} with {@code includeMediaInfo} set to {@code false}. */ - public DbxDelta getDelta(/*@Nullable*/String cursor) + public @Nonnull DbxDelta getDelta(@Nullable String cursor) throws DbxException { return getDelta(cursor, false); @@ -1495,7 +1493,7 @@ public DbxDelta getDelta(/*@Nullable*/String cursor) * A more generic version of {@link #getDelta}. You provide a collector, * which lets you process the delta entries as they arrive over the network. */ - public DbxDeltaC getDeltaC(Collector, C> collector, /*@Nullable*/String cursor, + public @Nonnull DbxDeltaC getDeltaC(@Nonnull Collector, C> collector, @Nullable String cursor, boolean includeMediaInfo) throws DbxException { @@ -1505,7 +1503,7 @@ public DbxDeltaC getDeltaC(Collector, C> collec /** * Same as {@link #getDeltaC(Collector, String, boolean)} with {@code includeMediaInfo} set to {@code false}. */ - public DbxDeltaC getDeltaC(Collector, C> collector, /*@Nullable*/String cursor) + public @Nonnull DbxDeltaC getDeltaC(@Nonnull Collector, C> collector, @Nullable String cursor) throws DbxException { return getDeltaC(collector, cursor, false); @@ -1524,7 +1522,7 @@ public DbxDeltaC getDeltaC(Collector, C> collec * @param pathPrefix * A path on Dropbox to limit results to. */ - public DbxDelta getDeltaWithPathPrefix(/*@Nullable*/String cursor, String pathPrefix, + public @Nonnull DbxDelta getDeltaWithPathPrefix(@Nullable String cursor, @Nonnull String pathPrefix, boolean includeMediaInfo) throws DbxException { @@ -1536,7 +1534,7 @@ public DbxDelta getDeltaWithPathPrefix(/*@Nullable*/String cursor, Str * Same as {@link #getDeltaWithPathPrefix(String, String, boolean)} with {@code includeMediaInfo} * set to {@code false}. */ - public DbxDelta getDeltaWithPathPrefix(/*@Nullable*/String cursor, String pathPrefix) + public @Nonnull DbxDelta getDeltaWithPathPrefix(@Nullable String cursor, @Nonnull String pathPrefix) throws DbxException { DbxPathV1.checkArg("path", pathPrefix); @@ -1547,8 +1545,7 @@ public DbxDelta getDeltaWithPathPrefix(/*@Nullable*/String cursor, Str * A more generic version of {@link #getDeltaWithPathPrefix}. You provide a collector, * which lets you process the delta entries as they arrive over the network. */ - public DbxDeltaC getDeltaCWithPathPrefix(Collector, C> collector, - /*@Nullable*/String cursor, String pathPrefix, + public @Nonnull DbxDeltaC getDeltaCWithPathPrefix(@Nonnull Collector, C> collector, @Nullable String cursor, @Nonnull String pathPrefix, boolean includeMediaInfo) throws DbxException { @@ -1560,20 +1557,19 @@ public DbxDeltaC getDeltaCWithPathPrefix(Collector DbxDeltaC getDeltaCWithPathPrefix(Collector, C> collector, - /*@Nullable*/String cursor, String pathPrefix) + public @Nonnull DbxDeltaC getDeltaCWithPathPrefix(@Nonnull Collector, C> collector, @Nullable String cursor, @Nonnull String pathPrefix) throws DbxException { return getDeltaCWithPathPrefix(collector, cursor, pathPrefix, false); } - private DbxDelta _getDelta(/*@Nullable*/String cursor, /*@Nullable*/String pathPrefix, boolean includeMediaInfo) + private @Nonnull DbxDelta _getDelta(@Nullable String cursor, @Nullable String pathPrefix, boolean includeMediaInfo) throws DbxException { String host = this.host.getApi(); String apiPath = "1/delta"; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "cursor", cursor, "path_prefix", pathPrefix, "include_media_info", includeMediaInfo ? "true" : null, @@ -1581,22 +1577,21 @@ private DbxDelta _getDelta(/*@Nullable*/String cursor, /*@Nullable*/St return doPost(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler>() { @Override - public DbxDelta handle(HttpRequestor.Response response) throws DbxException { + public @Nonnull DbxDelta handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); return DbxRequestUtil.readJsonFromResponse(new DbxDelta.Reader(DbxEntry.Reader), response); } }); } - private DbxDeltaC _getDeltaC(final Collector, C> collector, - /*@Nullable*/String cursor, /*@Nullable*/String pathPrefix, + private @Nonnull DbxDeltaC _getDeltaC(final @Nonnull Collector, C> collector, @Nullable String cursor, @Nullable String pathPrefix, boolean includeMediaInfo) throws DbxException { String host = this.host.getApi(); String apiPath = "1/delta"; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "cursor", cursor, "path_prefix", pathPrefix, "include_media_info", includeMediaInfo ? "true" : null, @@ -1604,7 +1599,7 @@ private DbxDeltaC _getDeltaC(final Collector, C return doPost(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler>() { @Override - public DbxDeltaC handle(HttpRequestor.Response response) throws DbxException { + public @Nonnull DbxDeltaC handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); return DbxRequestUtil.readJsonFromResponse(new DbxDeltaC.Reader(DbxEntry.Reader, collector), response); } @@ -1615,7 +1610,7 @@ public DbxDeltaC handle(HttpRequestor.Response response) throws DbxException * Get a cursor for the current state of a user's Dropbox folder. Can be passed to {@link #getDelta} * to retrieve changes since this method was called. */ - public String getDeltaLatestCursor(boolean includeMediaInfo) throws DbxException + public @Nonnull String getDeltaLatestCursor(boolean includeMediaInfo) throws DbxException { return _getDeltaLatestCursor(null, includeMediaInfo); } @@ -1624,7 +1619,7 @@ public String getDeltaLatestCursor(boolean includeMediaInfo) throws DbxException * Same as {@link #getDeltaLatestCursor(boolean)} with {@code includeMediaInfo} * set to {@code false}. */ - public String getDeltaLatestCursor() throws DbxException + public @Nonnull String getDeltaLatestCursor() throws DbxException { return _getDeltaLatestCursor(null, false); } @@ -1636,7 +1631,7 @@ public String getDeltaLatestCursor() throws DbxException * @param pathPrefix * A path on Dropbox to limit the cursor to. */ - public String getDeltaLatestCursorWithPathPrefix(String pathPrefix, boolean includeMediaInfo) throws DbxException + public @Nonnull String getDeltaLatestCursorWithPathPrefix(@Nonnull String pathPrefix, boolean includeMediaInfo) throws DbxException { DbxPathV1.checkArg("path", pathPrefix); return _getDeltaLatestCursor(pathPrefix, includeMediaInfo); @@ -1646,33 +1641,33 @@ public String getDeltaLatestCursorWithPathPrefix(String pathPrefix, boolean incl * Same as {@link #getDeltaLatestCursorWithPathPrefix(String, boolean)} with {@code includeMediaInfo} * set to {@code false}. */ - public String getDeltaLatestCursorWithPathPrefix(String pathPrefix) throws DbxException + public @Nonnull String getDeltaLatestCursorWithPathPrefix(@Nonnull String pathPrefix) throws DbxException { return getDeltaLatestCursorWithPathPrefix(pathPrefix, false); } - private String _getDeltaLatestCursor(/*@Nullable*/String pathPrefix, boolean includeMediaInfo) throws DbxException + private @Nonnull String _getDeltaLatestCursor(@Nullable String pathPrefix, boolean includeMediaInfo) throws DbxException { String host = this.host.getApi(); String apiPath = "1/delta/latest_cursor"; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "path_prefix", pathPrefix, "include_media_info", includeMediaInfo ? "true" : null, }; return doPost(host, apiPath, params, null, new DbxRequestUtil.ResponseHandler() { @Override - public String handle(HttpRequestor.Response response) throws DbxException { + public @Nonnull String handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); return DbxRequestUtil.readJsonFromResponse(LatestCursorReader, response); } }); } - private static JsonReader LatestCursorReader = new JsonReader() { + private static @Nonnull JsonReader LatestCursorReader = new JsonReader() { @Override - public String read(JsonParser parser) throws IOException, JsonReadException { + public @Nonnull String read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); String cursorId = null; @@ -1709,7 +1704,7 @@ public String read(JsonParser parser) throws IOException, JsonReadException { * @param timeout * How long poll should run before timing out, in seconds. */ - public DbxLongpollDeltaResult getLongpollDelta(String cursor, int timeout) + public @Nonnull DbxLongpollDeltaResult getLongpollDelta(@Nonnull String cursor, int timeout) throws DbxException { if (cursor == null) throw new IllegalArgumentException("'cursor' can't be null"); @@ -1729,7 +1724,7 @@ public DbxLongpollDeltaResult getLongpollDelta(String cursor, int timeout) null, new DbxRequestUtil.ResponseHandler() { @Override - public DbxLongpollDeltaResult handle(HttpRequestor.Response response) + public @Nonnull DbxLongpollDeltaResult handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); @@ -1765,9 +1760,9 @@ public DbxLongpollDeltaResult handle(HttpRequestor.Response response) * The metadata for the original file (not the thumbnail) or {@code null} if there * is no file at that path. */ - public DbxEntry./*@Nullable*/File getThumbnail( - DbxThumbnailSize sizeBound, DbxThumbnailFormat format, - String path, /*@Nullable*/String rev, OutputStream target) + public @Nullable DbxEntry.File getThumbnail( + @Nonnull DbxThumbnailSize sizeBound, @Nonnull DbxThumbnailFormat format, + @Nonnull String path, @Nullable String rev, @Nonnull OutputStream target) throws DbxException, IOException { if (target == null) throw new IllegalArgumentException("'target' can't be null"); @@ -1781,8 +1776,8 @@ public DbxLongpollDeltaResult handle(HttpRequestor.Response response) * Similar to {@link #getThumbnail}, except the thumbnail contents are returned via * a {@link Downloader}. */ - public /*@Nullable*/Downloader startGetThumbnail( - DbxThumbnailSize sizeBound, DbxThumbnailFormat format, String path, /*@Nullable*/String rev) + public @Nullable Downloader startGetThumbnail( + @Nonnull DbxThumbnailSize sizeBound, @Nonnull DbxThumbnailFormat format, @Nonnull String path, @Nullable String rev) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); @@ -1790,7 +1785,7 @@ public DbxLongpollDeltaResult handle(HttpRequestor.Response response) if (format == null) throw new IllegalArgumentException("'format' can't be null"); String apiPath = "1/thumbnails/auto" + path; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "size", sizeBound.ident, "format", format.ident, "rev", rev, @@ -1811,7 +1806,7 @@ public DbxLongpollDeltaResult handle(HttpRequestor.Response response) * @return * A list of metadata objects, one for each file revision. */ - public List getRevisions(String path) + public @Nonnull List getRevisions(@Nonnull String path) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); @@ -1819,11 +1814,11 @@ public List getRevisions(String path) String apiPath = "1/revisions/auto" + path; return doGet(host.getApi(), apiPath, null, null, new DbxRequestUtil.ResponseHandler>() { - public List handle(HttpRequestor.Response response) + public @Nonnull List handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); - Collector> collector = + Collector> collector = Collector.NullSkipper.>mk(new Collector.ArrayListCollector()); return DbxRequestUtil.readJsonFromResponse(JsonArrayReader.mk(DbxEntry.File.ReaderMaybeDeleted, collector), response); } @@ -1845,7 +1840,7 @@ public List handle(HttpRequestor.Response response) * If the specified {@code path}/{@code rev} couldn't be found, return {@code null}. * Otherwise, return metadata for the newly-created latest revision of the file. */ - public DbxEntry./*@Nullable*/File restoreFile(String path, String rev) + public @Nullable DbxEntry.File restoreFile(@Nonnull String path, @Nonnull String rev) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); @@ -1853,12 +1848,12 @@ public List handle(HttpRequestor.Response response) if (rev.length() == 0) throw new IllegalArgumentException("'rev' can't be empty"); String apiPath = "1/restore/auto" + path; - /*@Nullable*/String[] params = { + @Nullable String[] params = { "rev", rev, }; - return doGet(host.getApi(), apiPath, params, null, new DbxRequestUtil.ResponseHandler() { - public DbxEntry./*@Nullable*/File handle(HttpRequestor.Response response) + return doGet(host.getApi(), apiPath, params, null, new DbxRequestUtil.ResponseHandler() { + public @Nullable DbxEntry.File handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 404) return null; @@ -1879,7 +1874,7 @@ public List handle(HttpRequestor.Response response) * @return * The list of metadata entries that match the search query. */ - public List searchFileAndFolderNames(String basePath, String query) + public @Nonnull List searchFileAndFolderNames(@Nonnull String basePath, @Nonnull String query) throws DbxException { DbxPathV1.checkArg("basePath", basePath); @@ -1892,7 +1887,7 @@ public List searchFileAndFolderNames(String basePath, String query) return doPost(host.getApi(), apiPath, params, null, new DbxRequestUtil.ResponseHandler>() { @Override - public List handle(HttpRequestor.Response response) + public @Nonnull List handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); @@ -1913,7 +1908,7 @@ public List handle(HttpRequestor.Response response) * If there is no file or folder at that path, return {@code null}. Otherwise return * a shareable URL. */ - public /*@Nullable*/String createShareableUrl(String path) + public @Nullable String createShareableUrl(@Nonnull String path) throws DbxException { DbxPathV1.checkArg("path", path); @@ -1921,9 +1916,9 @@ public List handle(HttpRequestor.Response response) String apiPath = "1/shares/auto" + path; String[] params = {"short_url", "false"}; - return doPost(host.getApi(), apiPath, params, null, new DbxRequestUtil.ResponseHandler() { + return doPost(host.getApi(), apiPath, params, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/String handle(HttpRequestor.Response response) + public @Nullable String handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 404) return null; @@ -1945,16 +1940,16 @@ public List handle(HttpRequestor.Response response) * If there is no file at that path, return {@code null}. Otherwise return * a shareable URL along with the expiration time. */ - public /*@Nullable*/DbxUrlWithExpiration createTemporaryDirectUrl(String path) + public @Nullable DbxUrlWithExpiration createTemporaryDirectUrl(@Nonnull String path) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); String apiPath = "1/media/auto" + path; - return doPost(host.getApi(), apiPath, null, null, new DbxRequestUtil.ResponseHandler() { + return doPost(host.getApi(), apiPath, null, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/DbxUrlWithExpiration handle(HttpRequestor.Response response) + public @Nullable DbxUrlWithExpiration handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 404) return null; @@ -1985,17 +1980,17 @@ public List handle(HttpRequestor.Response response) * The copy ref's identifier, suitable for passing in to {@link #copyFromCopyRef}, * or {@code null} if the specified path does not exist. */ - public /*@Nullable*/String createCopyRef(String path) + public @Nullable String createCopyRef(@Nonnull String path) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); String apiPath = "1/copy_ref/auto" + path; - return doPost(host.getApi(), apiPath, null, null, new DbxRequestUtil.ResponseHandler() + return doPost(host.getApi(), apiPath, null, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/String handle(HttpRequestor.Response response) + public @Nullable String handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 404) return null; @@ -2008,18 +2003,18 @@ public List handle(HttpRequestor.Response response) private static final class CopyRef { - public final String id; - public final Date expires; + public final @Nonnull String id; + public final @Nonnull Date expires; - private CopyRef(String id, Date expires) + private CopyRef(@Nonnull String id, @Nonnull Date expires) { this.id = id; this.expires = expires; } - public static final JsonReader Reader = new JsonReader() { + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public CopyRef read(JsonParser parser) + public @Nonnull CopyRef read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -2064,7 +2059,7 @@ else if (fieldName.equals("expires")) { * If successful, returns the metadata for new copy of the file or folder, * otherwise returns {@code null}. */ - public /*@Nullable*/DbxEntry copy(String fromPath, String toPath) + public @Nullable DbxEntry copy(@Nonnull String fromPath, @Nonnull String toPath) throws DbxException { DbxPathV1.checkArg("fromPath", fromPath); @@ -2076,9 +2071,9 @@ else if (fieldName.equals("expires")) { "to_path", toPath, }; - return doPost(host.getApi(), "1/fileops/copy", params, null, new DbxRequestUtil.ResponseHandler() { + return doPost(host.getApi(), "1/fileops/copy", params, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/DbxEntry handle(HttpRequestor.Response response) + public @Nullable DbxEntry handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 403) return null; @@ -2094,7 +2089,7 @@ else if (fieldName.equals("expires")) { * Create a file or folder at {@code toPath} based on the given copy ref (created with * {@link #createCopyRef}). */ - public /*@Nullable*/DbxEntry copyFromCopyRef(String copyRef, String toPath) + public @Nullable DbxEntry copyFromCopyRef(@Nonnull String copyRef, @Nonnull String toPath) throws DbxException { if (copyRef == null) throw new IllegalArgumentException("'copyRef' can't be null"); @@ -2107,10 +2102,10 @@ else if (fieldName.equals("expires")) { "to_path", toPath, }; - return doPost(host.getApi(), "1/fileops/copy", params, null, new DbxRequestUtil.ResponseHandler() + return doPost(host.getApi(), "1/fileops/copy", params, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/DbxEntry handle(HttpRequestor.Response response) + public @Nullable DbxEntry handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); @@ -2128,7 +2123,7 @@ else if (fieldName.equals("expires")) { * If successful, returns the metadata for the newly created folder, otherwise * returns {@code null}. */ - public DbxEntry./*@Nullable*/Folder createFolder(String path) + public @Nullable DbxEntry.Folder createFolder(@Nonnull String path) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); @@ -2138,9 +2133,9 @@ else if (fieldName.equals("expires")) { "path", path, }; - return doPost(host.getApi(), "1/fileops/create_folder", params, null, new DbxRequestUtil.ResponseHandler() { + return doPost(host.getApi(), "1/fileops/create_folder", params, null, new DbxRequestUtil.ResponseHandler() { @Override - public DbxEntry./*@Nullable*/Folder handle(HttpRequestor.Response response) + public @Nullable DbxEntry.Folder handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 403) return null; @@ -2153,7 +2148,7 @@ else if (fieldName.equals("expires")) { /** * Delete a file or folder from Dropbox. */ - public void delete(String path) + public void delete(@Nonnull String path) throws DbxException { DbxPathV1.checkArgNonRoot("path", path); @@ -2165,7 +2160,7 @@ public void delete(String path) doPost(host.getApi(), "1/fileops/delete", params, null, new DbxRequestUtil.ResponseHandler() { @Override - public Void handle(HttpRequestor.Response response) + public @Nullable Void handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() != 200) throw DbxRequestUtil.unexpectedStatus(response); @@ -2181,7 +2176,7 @@ public Void handle(HttpRequestor.Response response) * If successful, returns the metadata for the file or folder at its new location, * otherwise returns {@code null}. */ - public /*@Nullable*/DbxEntry move(String fromPath, String toPath) + public @Nullable DbxEntry move(@Nonnull String fromPath, @Nonnull String toPath) throws DbxException { DbxPathV1.checkArgNonRoot("fromPath", fromPath); @@ -2193,10 +2188,10 @@ public Void handle(HttpRequestor.Response response) "to_path", toPath, }; - return doPost(host.getApi(), "1/fileops/move", params, null, new DbxRequestUtil.ResponseHandler() + return doPost(host.getApi(), "1/fileops/move", params, null, new DbxRequestUtil.ResponseHandler() { @Override - public /*@Nullable*/DbxEntry handle(HttpRequestor.Response response) + public @Nullable DbxEntry handle(@Nonnull HttpRequestor.Response response) throws DbxException { if (response.getStatusCode() == 403) return null; @@ -2211,8 +2206,8 @@ public Void handle(HttpRequestor.Response response) // -------------------------------------------------------- // Convenience function that calls RequestUtil.doGet with the first two parameters filled in. - private T doGet(String host, String path, /*@Nullable*/String/*@Nullable*/[] params, - /*@Nullable*/ArrayList headers, + private T doGet(String host, String path, @Nullable String[] params, + @Nullable ArrayList headers, DbxRequestUtil.ResponseHandler handler) throws DbxException { @@ -2220,10 +2215,10 @@ private T doGet(String host, String path, /*@Nullable*/String/*@Nullable*/[] } // Convenience function that calls RequestUtil.doPost with the first two parameters filled in. - public T doPost(String host, String path, - /*@Nullable*/String/*@Nullable*/[] params, - /*@Nullable*/ArrayList headers, - DbxRequestUtil.ResponseHandler handler) + public @Nullable T doPost(@Nonnull String host, @Nonnull String path, + @Nullable String[] params, + @Nullable ArrayList headers, + @Nonnull DbxRequestUtil.ResponseHandler handler) throws DbxException { return DbxRequestUtil.doPost(requestConfig, accessToken, USER_AGENT_ID, host, path, params, headers, handler); @@ -2252,7 +2247,7 @@ public T doPost(String host, String path, */ public static abstract class Uploader { - public abstract OutputStream getBody(); + public abstract @Nonnull OutputStream getBody(); /** * Cancel the upload. @@ -2271,6 +2266,6 @@ public static abstract class Uploader * to indicate that you're done. This will actually finish the underlying HTTP * request and return the uploaded file's {@link DbxEntry}. */ - public abstract DbxEntry.File finish() throws DbxException; + public abstract @Nonnull DbxEntry.File finish() throws DbxException; } } diff --git a/core/src/main/java/com/dropbox/core/v1/DbxDelta.java b/core/src/main/java/com/dropbox/core/v1/DbxDelta.java index 9ef6015a8..be58c513c 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxDelta.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxDelta.java @@ -1,5 +1,7 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.json.JsonArrayReader; import com.dropbox.core.json.JsonReadException; import com.dropbox.core.json.JsonReader; @@ -14,7 +16,6 @@ import java.io.IOException; import java.util.List; -/*>>> import checkers.nullness.quals.Nullable; */ /** * Represents a single "page" of results from a delta-style API call. @@ -42,7 +43,7 @@ public final class DbxDelta extends Dumpable /** * Apply these entries to your local state to catch up with the Dropbox server's state. */ - public final List> entries; + public final @Nonnull List> entries; /** * A string that is used by the server to keep track of which entries have already been @@ -54,7 +55,7 @@ public final class DbxDelta extends Dumpable * (such as a database) so you can resume continue you left off. *

*/ - public final String cursor; + public final @Nonnull String cursor; /** * If {@code true}, then there are more entries available. You can retrieve @@ -69,7 +70,7 @@ public final class DbxDelta extends Dumpable * @param cursor {@link #cursor} * @param hasMore {@link #hasMore} */ - public DbxDelta(boolean reset, List> entries, String cursor, boolean hasMore) + public DbxDelta(boolean reset, @Nonnull List> entries, @Nonnull String cursor, boolean hasMore) { this.reset = reset; this.entries = entries; @@ -77,7 +78,7 @@ public DbxDelta(boolean reset, List> entries, String cursor, boolean h this.hasMore = hasMore; } - protected void dumpFields(DumpWriter out) + protected void dumpFields(@Nonnull DumpWriter out) { out.f("reset").v(reset); out.f("hasMore").v(hasMore); @@ -90,19 +91,19 @@ protected void dumpFields(DumpWriter out) */ public static final class Reader extends JsonReader> { - public final JsonReader metadataReader; + public final @Nonnull JsonReader metadataReader; - public Reader(JsonReader metadataReader) + public Reader(@Nonnull JsonReader metadataReader) { this.metadataReader = metadataReader; } - public DbxDelta read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull DbxDelta read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return read(parser, metadataReader); } - public static DbxDelta read(JsonParser parser, JsonReader metadataReader) + public static @Nonnull DbxDelta read(@Nonnull JsonParser parser, @Nonnull JsonReader metadataReader) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -183,7 +184,7 @@ public static final class Entry extends Dumpable * To get the original case-preserved path, look in the {@link #metadata} field. *

*/ - public final String lcPath; + public final @Nonnull String lcPath; /** * If this is {@code null}, it means that this path doesn't exist on @@ -213,19 +214,19 @@ public static final class Entry extends Dumpable * * */ - public final /*@Nullable*/MD metadata; + public final @Nullable MD metadata; /** * @param lcPath {@link #lcPath} * @param metadata {@link #metadata} */ - public Entry(String lcPath, /*@Nullable*/MD metadata) + public Entry(@Nonnull String lcPath, @Nullable MD metadata) { this.lcPath = lcPath; this.metadata = metadata; } - protected void dumpFields(DumpWriter out) + protected void dumpFields(@Nonnull DumpWriter out) { out.f("lcPath").v(lcPath); out.f("metadata").v(metadata); @@ -236,19 +237,19 @@ protected void dumpFields(DumpWriter out) */ public static final class Reader extends JsonReader> { - public final JsonReader metadataReader; + public final @Nonnull JsonReader metadataReader; - public Reader(JsonReader metadataReader) + public Reader(@Nonnull JsonReader metadataReader) { this.metadataReader = metadataReader; } - public Entry read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull Entry read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return read(parser, metadataReader); } - public static Entry read(JsonParser parser, JsonReader metadataReader) + public static @Nonnull Entry read(@Nonnull JsonParser parser, @Nonnull JsonReader metadataReader) throws IOException, JsonReadException { JsonLocation arrayStart = JsonReader.expectArrayStart(parser); @@ -269,7 +270,7 @@ public static Entry read(JsonParser parser, JsonReader throw new JsonReadException("expecting a two-element array of [path, metadata], found a one-element array: " + jq(lcPath), arrayStart); } - /*@Nullable*/MD metadata; + @Nullable MD metadata; try { metadata = metadataReader.readOptional(parser); } diff --git a/core/src/main/java/com/dropbox/core/v1/DbxDeltaC.java b/core/src/main/java/com/dropbox/core/v1/DbxDeltaC.java index d75a7572c..3717d072f 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxDeltaC.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxDeltaC.java @@ -1,5 +1,7 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.dropbox.core.json.JsonArrayReader; import com.dropbox.core.json.JsonReadException; import com.dropbox.core.json.JsonReader; @@ -12,7 +14,6 @@ import java.io.IOException; -/*>>> import checkers.nullness.quals.Nullable; */ /** * Represents a single "page" of results from a delta-style API call. This is the more @@ -41,7 +42,7 @@ public class DbxDeltaC extends Dumpable /** * Apply these entries to your local state to catch up with the Dropbox server's state. */ - public final C entries; + public final @Nonnull C entries; /** * A string that is used by the server to keep track of which entries have already been @@ -53,7 +54,7 @@ public class DbxDeltaC extends Dumpable * (such as a database) so you can resume continue you left off. *

*/ - public final String cursor; + public final @Nonnull String cursor; /** * If {@code true}, then there are more entries available. You can retrieve @@ -68,7 +69,7 @@ public class DbxDeltaC extends Dumpable * @param cursor {@link #cursor} * @param hasMore {@link #hasMore} */ - public DbxDeltaC(boolean reset, C entries, String cursor, boolean hasMore) + public DbxDeltaC(boolean reset, @Nonnull C entries, @Nonnull String cursor, boolean hasMore) { this.reset = reset; this.entries = entries; @@ -76,7 +77,7 @@ public DbxDeltaC(boolean reset, C entries, String cursor, boolean hasMore) this.hasMore = hasMore; } - protected void dumpFields(DumpWriter out) + protected void dumpFields(@Nonnull DumpWriter out) { out.f("reset").v(reset); out.f("cursor").v(cursor); @@ -89,21 +90,21 @@ protected void dumpFields(DumpWriter out) */ public static final class Reader extends JsonReader> { - public final JsonReader metadataReader; - public final Collector, C> entryCollector; + public final @Nonnull JsonReader metadataReader; + public final @Nonnull Collector, C> entryCollector; - public Reader(JsonReader metadataReader, Collector, C> entryCollector) + public Reader(@Nonnull JsonReader metadataReader, @Nonnull Collector, C> entryCollector) { this.metadataReader = metadataReader; this.entryCollector = entryCollector; } - public DbxDeltaC read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull DbxDeltaC read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return read(parser, metadataReader, entryCollector); } - public static DbxDeltaC read(JsonParser parser, JsonReader metadataReader, Collector, C> entryCollector) + public static @Nonnull DbxDeltaC read(@Nonnull JsonParser parser, @Nonnull JsonReader metadataReader, @Nonnull Collector, C> entryCollector) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -184,7 +185,7 @@ public static final class Entry extends Dumpable * To get the original case-preserved path, look in the {@link #metadata metadata} field. *

*/ - public final String lcPath; + public final @Nonnull String lcPath; /** * If this is {@code null}, it means that this path doesn't exist on @@ -214,19 +215,19 @@ public static final class Entry extends Dumpable * * */ - public final /*@Nullable*/MD metadata; + public final @Nullable MD metadata; /** * @param lcPath {@link #lcPath} * @param metadata {@link #metadata} */ - public Entry(String lcPath, /*@Nullable*/MD metadata) + public Entry(@Nonnull String lcPath, @Nullable MD metadata) { this.lcPath = lcPath; this.metadata = metadata; } - protected void dumpFields(DumpWriter out) + protected void dumpFields(@Nonnull DumpWriter out) { out.f("lcPath").v(lcPath); out.f("metadata").v(metadata); @@ -237,19 +238,19 @@ protected void dumpFields(DumpWriter out) */ public static final class Reader extends JsonReader> { - public final JsonReader metadataReader; + public final @Nonnull JsonReader metadataReader; - public Reader(JsonReader metadataReader) + public Reader(@Nonnull JsonReader metadataReader) { this.metadataReader = metadataReader; } - public Entry read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull Entry read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return read(parser, metadataReader); } - public static Entry read(JsonParser parser, JsonReader metadataReader) + public static @Nonnull Entry read(@Nonnull JsonParser parser, @Nonnull JsonReader metadataReader) throws IOException, JsonReadException { JsonLocation arrayStart = JsonReader.expectArrayStart(parser); @@ -270,7 +271,7 @@ public static Entry read(JsonParser parser, JsonReader throw new JsonReadException("expecting a two-element array of [path, metadata], found a one-element array", arrayStart); } - /*@Nullable*/MD metadata; + @Nullable MD metadata; try { metadata = metadataReader.readOptional(parser); } @@ -289,4 +290,3 @@ public static Entry read(JsonParser parser, JsonReader } } } - diff --git a/core/src/main/java/com/dropbox/core/v1/DbxEntry.java b/core/src/main/java/com/dropbox/core/v1/DbxEntry.java index 558832bd2..fa18822e0 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxEntry.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxEntry.java @@ -1,5 +1,7 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.io.Serializable; import java.util.Date; @@ -17,8 +19,6 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -/*>>> import checkers.nullness.quals.Nullable; */ -/*>>> import checkers.nullness.quals.PolyNull; */ /** * Holds the metadata for a Dropbox file system entry. Can either be a regular file or a folder. @@ -32,7 +32,7 @@ public abstract class DbxEntry extends Dumpable implements Serializable * * @see DbxPathV1#getName */ - public final String name; + public final @Nonnull String name; /** * The path to the file or folder, relative to your application's root. @@ -44,7 +44,7 @@ public abstract class DbxEntry extends Dumpable implements Serializable * is relative to your application's App Folder within the user's Dropbox. *

*/ - public final String path; + public final @Nonnull String path; /** * The name of the icon to use for this file. The set of names returned by this call match up @@ -52,7 +52,7 @@ public abstract class DbxEntry extends Dumpable implements Serializable * field in * Dropbox's documentation for the {@code /metadata} HTTP endpoint. */ - public final String iconName; + public final @Nonnull String iconName; /** * Whether this file or folder might have a thumbnail image you can retrieve via @@ -67,7 +67,7 @@ public abstract class DbxEntry extends Dumpable implements Serializable * @param iconName {@link #iconName} * @param mightHaveThumbnail {@link #mightHaveThumbnail} */ - private DbxEntry(String path, String iconName, boolean mightHaveThumbnail) + private DbxEntry(@Nonnull String path, @Nonnull String iconName, boolean mightHaveThumbnail) { this.name = DbxPathV1.getName(path); this.path = path; @@ -75,7 +75,7 @@ private DbxEntry(String path, String iconName, boolean mightHaveThumbnail) this.mightHaveThumbnail = mightHaveThumbnail; } - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { w.v(path); w.f("iconName").v(iconName); @@ -98,15 +98,15 @@ protected void dumpFields(DumpWriter w) * If this metadata entry is a folder, return it as a {@code DbxEntry.Folder} * instance. If it's not a folder, return {@code null}. */ - public abstract Folder asFolder(); + public abstract @Nonnull Folder asFolder(); /** * If this metadata entry is a file, return it as a {@code DbxEntry.File} * instance. If it's not a file, return {@code null}. */ - public abstract File asFile(); + public abstract @Nonnull File asFile(); - protected boolean partialEquals(DbxEntry o) + protected boolean partialEquals(@Nonnull DbxEntry o) { if (!name.equals(o.name)) return false; if (!path.equals(o.path)) return false; @@ -138,21 +138,21 @@ public static final class Folder extends DbxEntry * @param iconName {@link #iconName} * @param mightHaveThumbnail {@link #mightHaveThumbnail} */ - public Folder(String path, String iconName, boolean mightHaveThumbnail) + public Folder(@Nonnull String path, @Nonnull String iconName, boolean mightHaveThumbnail) { super(path, iconName, mightHaveThumbnail); } - protected String getTypeName() { return "Folder"; } + protected @Nonnull String getTypeName() { return "Folder"; } public boolean isFolder() { return true; } public boolean isFile() { return false; } - public Folder asFolder() { return this; } - public File asFile() { throw new RuntimeException("not a file"); } + public @Nonnull Folder asFolder() { return this; } + public @Nonnull File asFile() { throw new RuntimeException("not a file"); } - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { - public final DbxEntry.Folder read(JsonParser parser) + public final @Nonnull DbxEntry.Folder read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = parser.getCurrentLocation(); @@ -165,12 +165,12 @@ public final DbxEntry.Folder read(JsonParser parser) }; - public boolean equals(/*@Nullable*/Object o) + public boolean equals(@Nullable Object o) { return o != null && getClass().equals(o.getClass()) && equals((Folder) o); } - public boolean equals(Folder o) + public boolean equals(@Nonnull Folder o) { if (!partialEquals(o)) return false; return true; @@ -200,7 +200,7 @@ public static final class File extends DbxEntry * be localized based on the {@link java.util.Locale Locale} in {@link DbxRequestConfig#userLocale} * (passed in to the {@link DbxClientV1} constructor). */ - public final String humanSize; + public final @Nonnull String humanSize; /** * The time the file was added, moved, or last had it's contents changed on the Dropbox @@ -208,7 +208,7 @@ public static final class File extends DbxEntry * the {@link #clientMtime} is a better estimate.) * */ - public final Date lastModified; + public final @Nonnull Date lastModified; /** * The modification time sent up by the Dropbox desktop client when the file was added @@ -220,25 +220,25 @@ public static final class File extends DbxEntry * a way to sort files by date (when displaying a list of files to the user). *

*/ - public final Date clientMtime; + public final @Nonnull Date clientMtime; /** * The revision of the file at this path. This can be used with {@link DbxClientV1#uploadFile} * and the {@link DbxWriteMode#update} mode to make sure you're overwriting the revision of * the file you think you're overwriting. */ - public final String rev; + public final @Nonnull String rev; /** * If this file is a photo, this may contain additional photo-related information. This field is * only populated if you use the {@code includeMediaInfo} */ - public final /*@Nullable*/PhotoInfo photoInfo; + public final @Nullable PhotoInfo photoInfo; /** * Contains details about this file if it is a video */ - public final /*@Nullable*/VideoInfo videoInfo; + public final @Nullable VideoInfo videoInfo; /** * @param path {@link #path} @@ -252,9 +252,9 @@ public static final class File extends DbxEntry * @param photoInfo {@link #photoInfo} * @param videoInfo {@link #videoInfo} */ - public File(String path, String iconName, boolean mightHaveThumbnail, long numBytes, String humanSize, - Date lastModified, Date clientMtime, String rev, - /*@Nullable*/PhotoInfo photoInfo, /*@Nullable*/VideoInfo videoInfo) + public File(@Nonnull String path, @Nonnull String iconName, boolean mightHaveThumbnail, long numBytes, @Nonnull String humanSize, + @Nonnull Date lastModified, @Nonnull Date clientMtime, @Nonnull String rev, + @Nullable PhotoInfo photoInfo, @Nullable VideoInfo videoInfo) { super(path, iconName, mightHaveThumbnail); this.numBytes = numBytes; @@ -269,13 +269,13 @@ public File(String path, String iconName, boolean mightHaveThumbnail, long numBy /** * Same as the other constructor except {@link #photoInfo} and {@link #videoInfo} are set to {@code null}. */ - public File(String path, String iconName, boolean mightHaveThumbnail, long numBytes, String humanSize, - Date lastModified, Date clientMtime, String rev) + public File(@Nonnull String path, @Nonnull String iconName, boolean mightHaveThumbnail, long numBytes, @Nonnull String humanSize, + @Nonnull Date lastModified, @Nonnull Date clientMtime, @Nonnull String rev) { this(path, iconName, mightHaveThumbnail, numBytes, humanSize, lastModified, clientMtime, rev, null, null); } - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { super.dumpFields(w); w.f("numBytes").v(numBytes); @@ -288,7 +288,7 @@ protected void dumpFields(DumpWriter w) } private static void nullablePendingField( - DumpWriter w, String fieldName, /*@Nullable*/T value, T pendingValue) + @Nonnull DumpWriter w, @Nonnull String fieldName, @Nullable T value, @Nonnull T pendingValue) { if (value == null) return; @@ -300,16 +300,16 @@ private static void nullablePendingField( } } - protected String getTypeName() { return "File"; } + protected @Nonnull String getTypeName() { return "File"; } public boolean isFolder() { return false; } public boolean isFile() { return true; } - public Folder asFolder() { throw new RuntimeException("not a folder"); } - public File asFile() { return this; } + public @Nonnull Folder asFolder() { throw new RuntimeException("not a folder"); } + public @Nonnull File asFile() { return this; } - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { - public final DbxEntry.File read(JsonParser parser) + public final @Nonnull DbxEntry.File read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = parser.getCurrentLocation(); @@ -322,9 +322,9 @@ public final DbxEntry.File read(JsonParser parser) }; - public static final JsonReader ReaderMaybeDeleted = new JsonReader() + public static final @Nonnull JsonReader ReaderMaybeDeleted = new JsonReader() { - public final DbxEntry./*@Nullable*/File read(JsonParser parser) + public final @Nullable DbxEntry.File read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = parser.getCurrentLocation(); @@ -339,12 +339,12 @@ public final DbxEntry.File read(JsonParser parser) }; - public boolean equals(/*@Nullable*/Object o) + public boolean equals(@Nullable Object o) { return o != null && getClass().equals(o.getClass()) && equals((File) o); } - public boolean equals(File o) + public boolean equals(@Nonnull File o) { if (!partialEquals(o)) return false; if (numBytes != o.numBytes) return false; @@ -378,22 +378,22 @@ public static final class PhotoInfo extends Dumpable /** * When the photo was taken. */ - public final /*@Nullable*/Date timeTaken; + public final @Nullable Date timeTaken; /** * Where the photo was taken. */ - public final /*@Nullable*/Location location; + public final @Nullable Location location; - public PhotoInfo(/*@Nullable*/Date timeTaken, /*@Nullable*/Location location) { + public PhotoInfo(@Nullable Date timeTaken, @Nullable Location location) { this.timeTaken = timeTaken; this.location = location; } - public static JsonReader Reader = new JsonReader() + public static @Nonnull JsonReader Reader = new JsonReader() { @Override - public PhotoInfo read(JsonParser parser) + public @Nonnull PhotoInfo read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonReader.expectObjectStart(parser); @@ -415,22 +415,22 @@ public PhotoInfo read(JsonParser parser) } }; - public static final PhotoInfo PENDING = new PhotoInfo(null, null); + public static final @Nonnull PhotoInfo PENDING = new PhotoInfo(null, null); @Override - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { w.f("timeTaken").v(timeTaken); w.f("location").v(location); } @Override - public boolean equals(/*@Nullable*/Object o) + public boolean equals(@Nullable Object o) { return o != null && getClass().equals(o.getClass()) && equals((PhotoInfo) o); } - public boolean equals(PhotoInfo o) + public boolean equals(@Nonnull PhotoInfo o) { // For "pending" values, it must be an exact match. if (o == PENDING || this == PENDING) return o == this; @@ -457,29 +457,29 @@ public static final class VideoInfo extends Dumpable /** * When the video was recorded. */ - public final /*@Nullable*/Date timeTaken; + public final @Nullable Date timeTaken; /** * Where the video was recorded. */ - public final /*@Nullable*/Location location; + public final @Nullable Location location; /** * The duration of the video, in seconds. */ - public final /*@Nullable*/Long duration; + public final @Nullable Long duration; - public VideoInfo(/*@Nullable*/Date timeTaken, /*@Nullable*/Location location, /*@Nullable*/Long duration) + public VideoInfo(@Nullable Date timeTaken, @Nullable Location location, @Nullable Long duration) { this.timeTaken = timeTaken; this.location = location; this.duration = duration; } - public static JsonReader Reader = new JsonReader() + public static @Nonnull JsonReader Reader = new JsonReader() { @Override - public VideoInfo read(JsonParser parser) + public @Nonnull VideoInfo read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonReader.expectObjectStart(parser); @@ -507,10 +507,10 @@ public VideoInfo read(JsonParser parser) /** * The singleton value used when the Dropbox server returns "pending" for */ - public static final VideoInfo PENDING = new VideoInfo(null, null, null); + public static final @Nonnull VideoInfo PENDING = new VideoInfo(null, null, null); @Override - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { w.f("timeTaken").v(timeTaken); w.f("location").v(location); @@ -518,12 +518,12 @@ protected void dumpFields(DumpWriter w) } @Override - public boolean equals(/*@Nullable*/Object o) + public boolean equals(@Nullable Object o) { return o != null && getClass().equals(o.getClass()) && equals((VideoInfo) o); } - public boolean equals(VideoInfo o) + public boolean equals(@Nonnull VideoInfo o) { // For "pending" values, it must be an exact match. if (o == PENDING || this == PENDING) return o == this; @@ -557,10 +557,10 @@ public Location(double latitude, double longitude) { this.longitude = longitude; } - public static JsonReader Reader = new JsonReader() + public static @Nonnull JsonReader Reader = new JsonReader() { @Override - public /*@Nullable*/Location read(JsonParser parser) + public @Nullable Location read(@Nonnull JsonParser parser) throws IOException, JsonReadException { Location location = null; @@ -579,7 +579,7 @@ public Location(double latitude, double longitude) { }; @Override - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { w.f("latitude").v(latitude); w.f("longitude").v(longitude); @@ -597,11 +597,11 @@ public int hashCode() { } @Override - public boolean equals(/*@Nullable*/Object o) { + public boolean equals(@Nullable Object o) { return o != null && getClass().equals(o.getClass()) && equals((Location) o); } - public boolean equals(Location o) + public boolean equals(@Nonnull Location o) { if (latitude != o.latitude) return false; if (longitude != o.longitude) return false; @@ -613,18 +613,18 @@ public boolean equals(Location o) // ------------------------------------------------------ // JSON parsing - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { - public final DbxEntry read(JsonParser parser) + public final @Nonnull DbxEntry read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return DbxEntry.read(parser, null).entry; } }; - public static final JsonReader ReaderMaybeDeleted = new JsonReader() + public static final @Nonnull JsonReader ReaderMaybeDeleted = new JsonReader() { - public final /*@Nullable*/DbxEntry read(JsonParser parser) + public final @Nullable DbxEntry read(@Nonnull JsonParser parser) throws IOException, JsonReadException { WithChildrenC wc = DbxEntry.readMaybeDeleted(parser, null); @@ -647,36 +647,36 @@ public static final class WithChildren extends Dumpable implements Serializable /** * The metadata for the base file or folder. */ - public final DbxEntry entry; + public final @Nonnull DbxEntry entry; /** * If {@link #entry} is a folder, this will contain a hash that identifies the folder's * contents. This value can be used with {@link DbxClientV1#getMetadataWithChildrenIfChanged} * to void downloading the folder contents if they havne't changed. */ - public final /*@PolyNull*/String hash; + public final @Nullable String hash; /** * If {@link #entry} is a folder, this will contain the metadata of the folder's * immediate children. If it's not a folder, this will be {@code null}. */ - public final /*@PolyNull*/List children; + public final @Nullable List children; /** * @param entry {@link #entry} * @param hash {@link #hash} * @param children {@link #children} */ - public WithChildren(DbxEntry entry, /*@PolyNull*/String hash, /*@PolyNull*/List children) + public WithChildren(@Nonnull DbxEntry entry, @Nullable String hash, @Nullable List children) { this.entry = entry; this.hash = hash; this.children = children; } - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { - public final WithChildren read(JsonParser parser) + public final @Nonnull WithChildren read(@Nonnull JsonParser parser) throws IOException, JsonReadException { WithChildrenC> c = DbxEntry.>read(parser, new Collector.ArrayListCollector()); @@ -684,9 +684,9 @@ public final WithChildren read(JsonParser parser) } }; - public static final JsonReader ReaderMaybeDeleted = new JsonReader() + public static final @Nonnull JsonReader ReaderMaybeDeleted = new JsonReader() { - public final /*@Nullable*/WithChildren read(JsonParser parser) + public final @Nullable WithChildren read(@Nonnull JsonParser parser) throws IOException, JsonReadException { WithChildrenC> c = DbxEntry.>readMaybeDeleted(parser, new Collector.ArrayListCollector()); @@ -695,12 +695,12 @@ public final WithChildren read(JsonParser parser) } }; - public boolean equals(/*@Nullable*/Object o) + public boolean equals(@Nullable Object o) { return o != null && getClass().equals(o.getClass()) && equals((WithChildren) o); } - public boolean equals(WithChildren o) + public boolean equals(@Nonnull WithChildren o) { if (children != null ? !children.equals(o.children) : o.children != null) return false; @@ -720,7 +720,7 @@ public int hashCode() } @Override - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { w.v(entry); w.f("hash").v(hash); @@ -738,27 +738,27 @@ public static final class WithChildrenC extends Dumpable implements Serializa { public static final long serialVersionUID = 0; - public final DbxEntry entry; + public final @Nonnull DbxEntry entry; /** * If {@link #entry} is a folder, this will contain a hash that identifies the folder's * contents. This value can be used with {@link DbxClientV1#getMetadataWithChildrenIfChanged} * to void downloading the folder contents if they havne't changed. */ - public final /*@PolyNull*/String hash; + public final @Nullable String hash; /** * If {@link #entry} is a folder, this will contain the metadata of the folder's * immediate children. If it's not a folder, this will be {@code null}. */ - public final /*@PolyNull*/C children; + public final @Nullable C children; /** * @param entry {@link #entry} * @param hash {@link #hash} * @param children {@link #children} */ - public WithChildrenC(DbxEntry entry, /*@PolyNull*/String hash, /*@PolyNull*/C children) + public WithChildrenC(@Nonnull DbxEntry entry, @Nullable String hash, @Nullable C children) { this.entry = entry; this.hash = hash; @@ -768,21 +768,21 @@ public WithChildrenC(DbxEntry entry, /*@PolyNull*/String hash, /*@PolyNull*/C ch public static class Reader extends JsonReader> { private final Collector collector; - public Reader(Collector collector) { this.collector = collector; } + public Reader(@Nonnull Collector collector) { this.collector = collector; } - public final WithChildrenC read(JsonParser parser) + public final @Nonnull WithChildrenC read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return DbxEntry.read(parser, collector); } } - public static class ReaderMaybeDeleted extends JsonReader> + public static class ReaderMaybeDeleted extends JsonReader> { private final Collector collector; - public ReaderMaybeDeleted(Collector collector) { this.collector = collector; } + public ReaderMaybeDeleted(@Nonnull Collector collector) { this.collector = collector; } - public final /*@Nullable*/WithChildrenC read(JsonParser parser) + public final @Nullable WithChildrenC read(@Nonnull JsonParser parser) throws IOException, JsonReadException { return DbxEntry.readMaybeDeleted(parser, collector); @@ -790,12 +790,12 @@ public static class ReaderMaybeDeleted extends JsonReader o) + public boolean equals(@Nonnull WithChildrenC o) { if (children != null ? !children.equals(o.children) : o.children != null) return false; @@ -815,7 +815,7 @@ public int hashCode() } @Override - protected void dumpFields(DumpWriter w) + protected void dumpFields(@Nonnull DumpWriter w) { w.v(entry); w.f("hash").v(hash); @@ -825,13 +825,13 @@ protected void dumpFields(DumpWriter w) } } - public static /*@Nullable*/WithChildrenC readMaybeDeleted(JsonParser parser, /*@Nullable*/Collector collector) + public static @Nullable WithChildrenC readMaybeDeleted(@Nonnull JsonParser parser, @Nullable Collector collector) throws IOException, JsonReadException { return _read(parser, collector, true); } - public static WithChildrenC read(JsonParser parser, /*@Nullable*/Collector collector) + public static @Nonnull WithChildrenC read(@Nonnull JsonParser parser, @Nullable Collector collector) throws IOException, JsonReadException { WithChildrenC r = _read(parser, collector, false); @@ -843,7 +843,7 @@ public static WithChildrenC read(JsonParser parser, /*@Nullable*/Collecto * @return * {@code null} if the entry is an 'is_deleted' entry. */ - private static /*@Nullable*/WithChildrenC _read(JsonParser parser, /*@Nullable*/Collector collector, boolean allowDeleted) + private static @Nullable WithChildrenC _read(JsonParser parser, @Nullable Collector collector, boolean allowDeleted) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); @@ -941,19 +941,19 @@ public static WithChildrenC read(JsonParser parser, /*@Nullable*/Collecto private static final class PendingReader extends JsonReader { - private final JsonReader reader; - private final T pendingValue; + private final @Nonnull JsonReader reader; + private final @Nonnull T pendingValue; - public PendingReader(JsonReader reader, T pendingValue) + public PendingReader(@Nonnull JsonReader reader, @Nonnull T pendingValue) { this.reader = reader; this.pendingValue = pendingValue; } - public static PendingReader mk(JsonReader reader, T pendingValue) { return new PendingReader(reader, pendingValue); } + public static @Nonnull PendingReader mk(@Nonnull JsonReader reader, @Nonnull T pendingValue) { return new PendingReader(reader, pendingValue); } @Override - public T read(JsonParser parser) + public @Nonnull T read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonToken token = parser.getCurrentToken(); diff --git a/core/src/main/java/com/dropbox/core/v1/DbxLongpollDeltaResult.java b/core/src/main/java/com/dropbox/core/v1/DbxLongpollDeltaResult.java index 33ca880f5..7c52cb76f 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxLongpollDeltaResult.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxLongpollDeltaResult.java @@ -8,6 +8,8 @@ import java.io.IOException; +import javax.annotation.Nonnull; + /** * The response from a longpoll_delta request. */ @@ -31,10 +33,10 @@ public DbxLongpollDeltaResult(boolean mightHaveChanges, long backoff) this.backoff = backoff; } - public static final JsonReader Reader = new JsonReader() + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public DbxLongpollDeltaResult read(JsonParser parser) throws IOException, JsonReadException + public @Nonnull DbxLongpollDeltaResult read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); diff --git a/core/src/main/java/com/dropbox/core/v1/DbxPathV1.java b/core/src/main/java/com/dropbox/core/v1/DbxPathV1.java index ec7d7eeb6..6420d9125 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxPathV1.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxPathV1.java @@ -1,8 +1,9 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import static com.dropbox.core.util.StringUtil.jq; -/*>>> import checkers.nullness.quals.Nullable; */ /** * Utility functions for working with Dropbox paths. This SDK uses {@code String}s @@ -17,13 +18,13 @@ */ public class DbxPathV1 { - public static boolean isValid(String path) + public static boolean isValid(@Nonnull String path) { String error = findError(path); return (error == null); } - public static /*@Nullable*/String findError(String path) + public static @Nullable String findError(@Nonnull String path) { if (!path.startsWith("/")) return "must start with \"/\""; if (path.length() == 1) return null; // Special case for "/" @@ -38,7 +39,7 @@ public static boolean isValid(String path) return null; } - public static void checkArg(String argName, String value) + public static void checkArg(@Nonnull String argName, @Nonnull String value) { if (value == null) { throw new IllegalArgumentException("'" + argName + "' should not be null"); @@ -49,7 +50,7 @@ public static void checkArg(String argName, String value) } } - public static void checkArgNonRoot(String argName, String value) + public static void checkArgNonRoot(@Nonnull String argName, @Nonnull String value) { if ("/".equals(value)) { throw new IllegalArgumentException("'" + argName + "' should not be the root path (\"/\")"); @@ -65,7 +66,7 @@ public static void checkArgNonRoot(String argName, String value) *
  • {@code getName("/Photos/Home.jpeg")} → {@code "Home.jpeg"}
  • * */ - public static String getName(String path) + public static @Nonnull String getName(@Nonnull String path) { if (path == null) throw new IllegalArgumentException("'path' can't be null"); if (!path.startsWith("/")) throw new IllegalArgumentException("Not a valid path. Doesn't start with a \"/\": \"" + path + "\""); @@ -78,7 +79,7 @@ public static String getName(String path) return path.substring(start+1); } - public static String[] split(String path) + public static @Nonnull String[] split(@Nonnull String path) { if (path == null) throw new IllegalArgumentException("'path' can't be null"); if (!path.startsWith("/")) throw new IllegalArgumentException("Not a valid path. Doesn't start with a \"/\": \"" + path + "\""); @@ -97,7 +98,7 @@ public static String[] split(String path) *
  • {@code getParent("/Photos/Recent/Home.jpeg")} → {@code "/Photos/Recent"}
  • * */ - public static /*@Nullable*/String getParent(String path) + public static @Nullable String getParent(@Nonnull String path) { if (path == null) throw new IllegalArgumentException("'path' can't be null"); if (!path.startsWith("/")) throw new IllegalArgumentException("Not a valid path. Doesn't start with a \"/\": \"" + path + "\""); diff --git a/core/src/main/java/com/dropbox/core/v1/DbxThumbnailFormat.java b/core/src/main/java/com/dropbox/core/v1/DbxThumbnailFormat.java index 1cf74cf4a..4a1d53dac 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxThumbnailFormat.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxThumbnailFormat.java @@ -1,13 +1,15 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; + /** * Thumbnail image format presets, to be used with {@link DbxClientV1#getThumbnail}. */ public class DbxThumbnailFormat { - public final String ident; + public final @Nonnull String ident; - public DbxThumbnailFormat(String ident) + public DbxThumbnailFormat(@Nonnull String ident) { this.ident = ident; } @@ -15,13 +17,13 @@ public DbxThumbnailFormat(String ident) /** * JPEG format, preferred over PNG for photographic images. */ - public static final DbxThumbnailFormat JPEG = new DbxThumbnailFormat("jpeg"); + public static final @Nonnull DbxThumbnailFormat JPEG = new DbxThumbnailFormat("jpeg"); /** * PNG format, preferred over JPEG for non-photographic images, such as * screenshots and digital art. */ - public static final DbxThumbnailFormat PNG = new DbxThumbnailFormat("png"); + public static final @Nonnull DbxThumbnailFormat PNG = new DbxThumbnailFormat("png"); /** * Try and guess the right {@code DbxThumbnailFormat} to use based on the image's file @@ -34,7 +36,7 @@ public DbxThumbnailFormat(String ident) * DbxThumbnailFormat.bestForFileName("/family.jpg"); // returns DbxThumbnailFormat.JPEG * */ - public static DbxThumbnailFormat bestForFileName(String fileName, DbxThumbnailFormat fallback) + public static @Nonnull DbxThumbnailFormat bestForFileName(@Nonnull String fileName, @Nonnull DbxThumbnailFormat fallback) { fileName = fileName.toLowerCase(); if (fileName.endsWith(".png") || fileName.endsWith(".gif")) { diff --git a/core/src/main/java/com/dropbox/core/v1/DbxThumbnailSize.java b/core/src/main/java/com/dropbox/core/v1/DbxThumbnailSize.java index 0ff555c0f..1173e547f 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxThumbnailSize.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxThumbnailSize.java @@ -1,22 +1,24 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; + /** * Thumbnail size presets, to be used with {@link DbxClientV1#getThumbnail}. */ public class DbxThumbnailSize { - public final String ident; + public final @Nonnull String ident; public final int width; public final int height; - public DbxThumbnailSize(String ident, int width, int height) + public DbxThumbnailSize(@Nonnull String ident, int width, int height) { this.ident = ident; this.width = width; this.height = height; } - public String toString() + public @Nonnull String toString() { return "(" + ident + " " + width + "x" + height + ")"; } @@ -24,25 +26,25 @@ public String toString() /** * 32x32 pixels. */ - public static final DbxThumbnailSize w32h32 = new DbxThumbnailSize("xs", 32, 32); + public static final @Nonnull DbxThumbnailSize w32h32 = new DbxThumbnailSize("xs", 32, 32); /** * 64x64 pixels. */ - public static final DbxThumbnailSize w64h64 = new DbxThumbnailSize("s", 64, 64); + public static final @Nonnull DbxThumbnailSize w64h64 = new DbxThumbnailSize("s", 64, 64); /** * 128x128 pixels. */ - public static final DbxThumbnailSize w128h128 = new DbxThumbnailSize("m", 128, 128); + public static final @Nonnull DbxThumbnailSize w128h128 = new DbxThumbnailSize("m", 128, 128); /** * 640x480 pixels. */ - public static final DbxThumbnailSize w640h480 = new DbxThumbnailSize("l", 640, 480); + public static final @Nonnull DbxThumbnailSize w640h480 = new DbxThumbnailSize("l", 640, 480); /** * 1024x768 pixels. */ - public static final DbxThumbnailSize w1024h768 = new DbxThumbnailSize("xl", 1024, 768); + public static final @Nonnull DbxThumbnailSize w1024h768 = new DbxThumbnailSize("xl", 1024, 768); } diff --git a/core/src/main/java/com/dropbox/core/v1/DbxUrlWithExpiration.java b/core/src/main/java/com/dropbox/core/v1/DbxUrlWithExpiration.java index 53a65f1c0..12f4a85f9 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxUrlWithExpiration.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxUrlWithExpiration.java @@ -10,20 +10,22 @@ import java.io.IOException; import java.util.Date; +import javax.annotation.Nonnull; + public final class DbxUrlWithExpiration { - public final String url; - public final Date expires; + public final @Nonnull String url; + public final @Nonnull Date expires; - public DbxUrlWithExpiration(String url, Date expires) + public DbxUrlWithExpiration(@Nonnull String url, @Nonnull Date expires) { this.url = url; this.expires = expires; } - public static final JsonReader Reader = new JsonReader() { + public static final @Nonnull JsonReader Reader = new JsonReader() { @Override - public DbxUrlWithExpiration read(JsonParser parser) + public @Nonnull DbxUrlWithExpiration read(@Nonnull JsonParser parser) throws IOException, JsonReadException { JsonLocation top = JsonReader.expectObjectStart(parser); diff --git a/core/src/main/java/com/dropbox/core/v1/DbxWriteMode.java b/core/src/main/java/com/dropbox/core/v1/DbxWriteMode.java index a1a082512..b09db7013 100644 --- a/core/src/main/java/com/dropbox/core/v1/DbxWriteMode.java +++ b/core/src/main/java/com/dropbox/core/v1/DbxWriteMode.java @@ -1,5 +1,7 @@ package com.dropbox.core.v1; +import javax.annotation.Nonnull; + /** * Describes how a file should be saved when it is written to Dropbox. Do not call * the constructor. Instead, call one of the three static functions: {@link #add}, @@ -10,8 +12,8 @@ public final class DbxWriteMode // NOTE: The current implementation just holds the URL parameters that we pass // to /files_put. If the upload mode becomes used in other calls, we may need // to switch the implementation over to be less tied to that specific endpoint. - final String[] params; - DbxWriteMode(String... params) + final @Nonnull String[] params; + DbxWriteMode(@Nonnull String... params) { this.params = params; } @@ -30,7 +32,7 @@ public final class DbxWriteMode * returned by the API call. *

    */ - public static DbxWriteMode add() { return AddInstance; } + public static @Nonnull DbxWriteMode add() { return AddInstance; } private static final DbxWriteMode AddInstance = new DbxWriteMode("overwrite", "false"); /** @@ -39,7 +41,7 @@ public final class DbxWriteMode * If there's a folder at that path, however, it will not be overwritten and the * API call will fail. */ - public static DbxWriteMode force() { return ForceInstance; } + public static @Nonnull DbxWriteMode force() { return ForceInstance; } private static final DbxWriteMode ForceInstance = new DbxWriteMode("overwrite", "true"); /** @@ -66,7 +68,7 @@ public final class DbxWriteMode * returned by the API call. *

    */ - public static DbxWriteMode update(String revisionToReplace) + public static @Nonnull DbxWriteMode update(@Nonnull String revisionToReplace) { return new DbxWriteMode("parent_rev", revisionToReplace); } diff --git a/core/src/main/java/com/dropbox/core/v2/DbxAppClientV2.java b/core/src/main/java/com/dropbox/core/v2/DbxAppClientV2.java index 2e04f6473..629c47a92 100644 --- a/core/src/main/java/com/dropbox/core/v2/DbxAppClientV2.java +++ b/core/src/main/java/com/dropbox/core/v2/DbxAppClientV2.java @@ -9,6 +9,9 @@ import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Use this class to make remote calls to the Dropbox API app endpoints. App endpoints expose * actions you can perform as a Dropbox app without user authorization. You'll need your app key @@ -28,7 +31,7 @@ public class DbxAppClientV2 extends DbxAppClientV2Base { * @param key Dropbox app key (e.g. consumer key in OAuth) * @param secret Dropbox app secret (e.g. consumer secret in OAuth) */ - public DbxAppClientV2(DbxRequestConfig requestConfig, String key, String secret) { + public DbxAppClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull String key, @Nonnull String secret) { this(requestConfig, key, secret, DbxHost.DEFAULT); } @@ -43,7 +46,10 @@ public DbxAppClientV2(DbxRequestConfig requestConfig, String key, String secret) * @param host Dropbox hosts to send requests to (used for mocking and * testing) */ - public DbxAppClientV2(DbxRequestConfig requestConfig, String key, String secret, DbxHost host) { + public DbxAppClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String key, + @Nonnull String secret, + @Nonnull DbxHost host) { super(new DbxAppRawClientV2(requestConfig, key, secret, host, null)); } @@ -60,7 +66,11 @@ public DbxAppClientV2(DbxRequestConfig requestConfig, String key, String secret, * @param userId The user ID of the current Dropbox account. Used for * multi-Dropbox account use-case. */ - public DbxAppClientV2(DbxRequestConfig requestConfig, String key, String secret, DbxHost host, String userId) { + public DbxAppClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String key, + @Nonnull String secret, + @Nonnull DbxHost host, + @Nullable String userId) { super(new DbxAppRawClientV2(requestConfig, key, secret, host, userId)); } @@ -68,17 +78,21 @@ public DbxAppClientV2(DbxRequestConfig requestConfig, String key, String secret, * {@link DbxRawClientV2} raw client that adds app auth headers to all requests. */ private static final class DbxAppRawClientV2 extends DbxRawClientV2 { - private final String key; - private final String secret; + private final @Nonnull String key; + private final @Nonnull String secret; - private DbxAppRawClientV2(DbxRequestConfig requestConfig, String key, String secret, DbxHost host, String userId) { + private DbxAppRawClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String key, + @Nonnull String secret, + @Nonnull DbxHost host, + @Nullable String userId) { super(requestConfig, host, userId, null); this.key = key; this.secret = secret; } @Override - public DbxRefreshResult refreshAccessToken() { + public @Nullable DbxRefreshResult refreshAccessToken() { //no op return null; } @@ -94,13 +108,13 @@ public boolean needsRefreshAccessToken() { } @Override - protected void addAuthHeaders(List headers) { + protected void addAuthHeaders(@Nonnull List headers) { DbxRequestUtil.removeAuthHeader(headers); DbxRequestUtil.addBasicAuthHeader(headers, key, secret); } @Override - protected DbxRawClientV2 withPathRoot(PathRoot pathRoot) { + protected @Nonnull DbxRawClientV2 withPathRoot(@Nonnull PathRoot pathRoot) { throw new UnsupportedOperationException("App endpoints don't support Dropbox-API-Path-Root header."); } } diff --git a/core/src/main/java/com/dropbox/core/v2/DbxClientV2.java b/core/src/main/java/com/dropbox/core/v2/DbxClientV2.java index 680c33201..606450a2a 100644 --- a/core/src/main/java/com/dropbox/core/v2/DbxClientV2.java +++ b/core/src/main/java/com/dropbox/core/v2/DbxClientV2.java @@ -12,6 +12,9 @@ import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Use this class to make remote calls to the Dropbox API user endpoints. User * endpoints expose actions you can perform as a Dropbox user. You'll need an @@ -32,7 +35,7 @@ public class DbxClientV2 extends DbxClientV2Base { * gives your app the ability to make Dropbox API calls. Typically * acquired through {@link com.dropbox.core.DbxWebAuth} */ - public DbxClientV2(DbxRequestConfig requestConfig, String accessToken) { + public DbxClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull String accessToken) { this(requestConfig, accessToken, DbxHost.DEFAULT, null); } @@ -47,7 +50,7 @@ public DbxClientV2(DbxRequestConfig requestConfig, String accessToken) { * @param userId The user ID of the current Dropbox account. Used for * multi-Dropbox account use-case. */ - public DbxClientV2(DbxRequestConfig requestConfig, String accessToken, String userId) { + public DbxClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull String accessToken, @Nullable String userId) { this(requestConfig, accessToken, DbxHost.DEFAULT, userId); } @@ -62,7 +65,7 @@ public DbxClientV2(DbxRequestConfig requestConfig, String accessToken, String us * @param requestConfig Default attributes to use for each request * @param credential The credential object containing all the information for authentication. */ - public DbxClientV2(DbxRequestConfig requestConfig, DbxCredential credential) { + public DbxClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull DbxCredential credential) { this(requestConfig, credential, DbxHost.DEFAULT, null, null); } @@ -78,7 +81,7 @@ public DbxClientV2(DbxRequestConfig requestConfig, DbxCredential credential) { * @param host Dropbox hosts to send requests to (used for mocking and * testing) */ - public DbxClientV2(DbxRequestConfig requestConfig, String accessToken, DbxHost host) { + public DbxClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull String accessToken, @Nonnull DbxHost host) { this(requestConfig, accessToken, host, null); } @@ -95,16 +98,19 @@ public DbxClientV2(DbxRequestConfig requestConfig, String accessToken, DbxHost h * @param userId The user ID of the current Dropbox account. Used for multi-Dropbox * account use-case. */ - public DbxClientV2(DbxRequestConfig requestConfig, String accessToken, DbxHost host, String userId) { + public DbxClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String accessToken, + @Nonnull DbxHost host, + @Nullable String userId) { this(requestConfig, new DbxCredential(accessToken), host, userId, null); } private DbxClientV2( - DbxRequestConfig requestConfig, - DbxCredential credential, - DbxHost host, - String userId, - PathRoot pathRoot) { + @Nonnull DbxRequestConfig requestConfig, + @Nonnull DbxCredential credential, + @Nonnull DbxHost host, + @Nullable String userId, + @Nullable PathRoot pathRoot) { super(new DbxUserRawClientV2(requestConfig, credential, host, userId, pathRoot)); } @@ -115,7 +121,7 @@ private DbxClientV2( * * @param client Raw v2 client ot use for issuing requests */ - DbxClientV2(DbxRawClientV2 client) { + DbxClientV2(@Nonnull DbxRawClientV2 client) { super(client); } @@ -133,7 +139,7 @@ private DbxClientV2( * * @throws IllegalArgumentException If {@code pathRoot} is {@code null} */ - public DbxClientV2 withPathRoot(PathRoot pathRoot) { + public @Nonnull DbxClientV2 withPathRoot(@Nonnull PathRoot pathRoot) { if (pathRoot == null) { throw new IllegalArgumentException("'pathRoot' should not be null"); } @@ -150,7 +156,7 @@ public DbxClientV2 withPathRoot(PathRoot pathRoot) { * token. * @throws DbxException If refresh failed before of general problems like network issue. */ - public DbxRefreshResult refreshAccessToken() throws DbxException { + public @Nonnull DbxRefreshResult refreshAccessToken() throws DbxException { return this._client.refreshAccessToken(); } @@ -158,10 +164,13 @@ public DbxRefreshResult refreshAccessToken() throws DbxException { * {@link DbxRawClientV2} raw client that adds user OAuth2 auth headers to all requests. */ private static final class DbxUserRawClientV2 extends DbxRawClientV2 { - private final DbxCredential credential; + private final @Nonnull DbxCredential credential; - DbxUserRawClientV2(DbxRequestConfig requestConfig, DbxCredential credential, DbxHost host, - String userId, PathRoot pathRoot) { + DbxUserRawClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull DbxCredential credential, + @Nonnull DbxHost host, + @Nullable String userId, + @Nullable PathRoot pathRoot) { super(requestConfig, host, userId, pathRoot); if (credential == null) throw new NullPointerException("credential"); @@ -169,7 +178,7 @@ private static final class DbxUserRawClientV2 extends DbxRawClientV2 { } @Override - public DbxRefreshResult refreshAccessToken() throws DbxException { + public @Nonnull DbxRefreshResult refreshAccessToken() throws DbxException { credential.refresh(this.getRequestConfig()); return new DbxRefreshResult(credential.getAccessToken(), (credential.getExpiresAt() - System.currentTimeMillis())/1000); } @@ -185,13 +194,13 @@ public boolean needsRefreshAccessToken() { } @Override - protected void addAuthHeaders(List headers) { + protected void addAuthHeaders(@Nonnull List headers) { DbxRequestUtil.removeAuthHeader(headers); DbxRequestUtil.addAuthHeader(headers, credential.getAccessToken()); } @Override - protected DbxRawClientV2 withPathRoot(PathRoot pathRoot) { + protected @Nonnull DbxRawClientV2 withPathRoot(@Nonnull PathRoot pathRoot) { return new DbxUserRawClientV2( this.getRequestConfig(), this.credential, diff --git a/core/src/main/java/com/dropbox/core/v2/DbxDownloadStyleBuilder.java b/core/src/main/java/com/dropbox/core/v2/DbxDownloadStyleBuilder.java index e8cfda33c..10da210cb 100644 --- a/core/src/main/java/com/dropbox/core/v2/DbxDownloadStyleBuilder.java +++ b/core/src/main/java/com/dropbox/core/v2/DbxDownloadStyleBuilder.java @@ -14,6 +14,9 @@ import java.io.IOException; import java.io.OutputStream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * The common interface for all builders associated with download style methods. After setting any * optional request parameters, use {@link #start} or {@link #download} to initiate the request. @@ -57,15 +60,15 @@ * @param The return type of the {@link DbxDownloader} */ public abstract class DbxDownloadStyleBuilder { - private Long start; - private Long length; + private @Nullable Long start; + private @Nullable Long length; protected DbxDownloadStyleBuilder() { this.start = null; this.length = null; } - protected List getHeaders() { + protected @Nonnull List getHeaders() { if (start == null) { return Collections.emptyList(); } @@ -95,7 +98,7 @@ protected List getHeaders() { * * @throws DbxException if an error occursing issuing the request */ - public abstract DbxDownloader start() throws DbxException; + public abstract @Nonnull DbxDownloader start() throws DbxException; /** * Sets the partial byte range to download. @@ -113,7 +116,7 @@ protected List getHeaders() { * * @throws IllegalArgumentException if {@code start} or {@code length} are negative */ - public DbxDownloadStyleBuilder range(long start, long length) { + public @Nonnull DbxDownloadStyleBuilder range(long start, long length) { if (start < 0) throw new IllegalArgumentException("start must be non-negative"); if (length < 1) throw new IllegalArgumentException("length must be positive"); @@ -138,7 +141,7 @@ public DbxDownloadStyleBuilder range(long start, long length) { * * @throws IllegalArgumentException if {@code start} is negative */ - public DbxDownloadStyleBuilder range(long start) { + public @Nonnull DbxDownloadStyleBuilder range(long start) { if (start < 0) throw new IllegalArgumentException("start must be non-negative"); this.start = start; @@ -161,7 +164,7 @@ public DbxDownloadStyleBuilder range(long start) { * @throws DbxException if an error occurs reading the response or response body * @throws IOException if an error occurs writing the response body to the output stream. */ - public R download(OutputStream out) throws DbxException, IOException { + public @Nullable R download(@Nonnull OutputStream out) throws DbxException, IOException { return start().download(out); } } diff --git a/core/src/main/java/com/dropbox/core/v2/DbxPathV2.java b/core/src/main/java/com/dropbox/core/v2/DbxPathV2.java index a8339e198..5332665f0 100644 --- a/core/src/main/java/com/dropbox/core/v2/DbxPathV2.java +++ b/core/src/main/java/com/dropbox/core/v2/DbxPathV2.java @@ -1,6 +1,7 @@ package com.dropbox.core.v2; -/*>>> import checkers.nullness.quals.Nullable; */ +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * Utility functions for working with Dropbox paths. This SDK uses {@code String}s @@ -15,13 +16,13 @@ */ public class DbxPathV2 { - public static boolean isValid(String path) + public static boolean isValid(@Nonnull String path) { String error = findError(path); return (error == null); } - public static /*@Nullable*/String findError(String path) + public static @Nullable String findError(@Nonnull String path) { if (path.length() == 0) return null; // Special case for "" @@ -44,7 +45,7 @@ public static boolean isValid(String path) *
  • {@code getName("/Photos/Home.jpeg")} → {@code "Home.jpeg"}
  • * */ - public static String getName(String path) + public static @Nullable String getName(@Nonnull String path) { if (path == null) throw new IllegalArgumentException("'path' can't be null"); if (path.length() == 0) return null; @@ -58,7 +59,7 @@ public static String getName(String path) return path.substring(start+1); } - public static String[] split(String path) + public static @Nonnull String[] split(@Nonnull String path) { if (path == null) throw new IllegalArgumentException("'path' can't be null"); if (path.length() == 0) return new String[0]; @@ -77,7 +78,7 @@ public static String[] split(String path) *
  • {@code getParent("/Photos/Recent/Home.jpeg")} → {@code "/Photos/Recent"}
  • * */ - public static /*@Nullable*/String getParent(String path) + public static @Nullable String getParent(@Nonnull String path) { if (path == null) throw new IllegalArgumentException("'path' can't be null"); if (path.length() == 0) return null; diff --git a/core/src/main/java/com/dropbox/core/v2/DbxRawClientV2.java b/core/src/main/java/com/dropbox/core/v2/DbxRawClientV2.java index 3a770df3f..4b22dd62e 100644 --- a/core/src/main/java/com/dropbox/core/v2/DbxRawClientV2.java +++ b/core/src/main/java/com/dropbox/core/v2/DbxRawClientV2.java @@ -35,10 +35,9 @@ import java.util.List; import java.util.Random; -/*>>> import checkers.nullness.quals.NonNull; */ -/*>>> import checkers.nullness.quals.Nullable; */ -/*>>> import checkers.nullness.quals.MonotonicNonNull; */ -/*>>> import checkers.initialization.quals.Initialized; */ +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Use this class to make remote calls to the Dropbox API. You'll need an access token first, @@ -50,18 +49,18 @@ *

    */ public abstract class DbxRawClientV2 { - public static final String USER_AGENT_ID = "OfficialDropboxJavaSDKv2"; + public static final @Nonnull String USER_AGENT_ID = "OfficialDropboxJavaSDKv2"; - private static final JsonFactory JSON = new JsonFactory(); - private static final Random RAND = new Random(); + private static final @Nonnull JsonFactory JSON = new JsonFactory(); + private static final @Nonnull Random RAND = new Random(); - private final DbxRequestConfig requestConfig; - private final DbxHost host; + private final @Nonnull DbxRequestConfig requestConfig; + private final @Nonnull DbxHost host; /* for multiple Dropbox account use-case */ - private final String userId; + private final @Nullable String userId; - private final PathRoot pathRoot; + private final @Nullable PathRoot pathRoot; /** * @param requestConfig Configuration controlling How requests should be issued to Dropbox @@ -70,7 +69,10 @@ public abstract class DbxRawClientV2 { * @param userId The user ID of the current Dropbox account. Used for multi-Dropbox account use-case. * @param pathRoot We will send this value in Dropbox-API-Path-Root header if it presents. */ - protected DbxRawClientV2(DbxRequestConfig requestConfig, DbxHost host, String userId, PathRoot pathRoot) { + protected DbxRawClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull DbxHost host, + @Nullable String userId, + @Nullable PathRoot pathRoot) { if (requestConfig == null) throw new NullPointerException("requestConfig"); if (host == null) throw new NullPointerException("host"); @@ -85,9 +87,9 @@ protected DbxRawClientV2(DbxRequestConfig requestConfig, DbxHost host, String us * * @param headers List of request headers. Add authentication headers to this list. */ - protected abstract void addAuthHeaders(List headers); + protected abstract void addAuthHeaders(@Nonnull List headers); - public abstract DbxRefreshResult refreshAccessToken() throws DbxException; + public abstract @Nullable DbxRefreshResult refreshAccessToken() throws DbxException; protected abstract boolean canRefreshAccessToken(); @@ -110,15 +112,15 @@ private void refreshAccessTokenIfNeeded() throws DbxException { * * @param pathRoot {@code pathRoot} object containing the content for Dropbox-API-Path-Root header. */ - protected abstract DbxRawClientV2 withPathRoot(PathRoot pathRoot); + protected abstract @Nonnull DbxRawClientV2 withPathRoot(@Nonnull PathRoot pathRoot); - public ResT rpcStyle(final String host, - final String path, - final ArgT arg, + public @Nullable ResT rpcStyle(final @Nonnull String host, + final @Nonnull String path, + final @Nullable ArgT arg, final boolean noAuth, - final StoneSerializer argSerializer, - final StoneSerializer responseSerializer, - final StoneSerializer errorSerializer) + final @Nonnull StoneSerializer argSerializer, + final @Nonnull StoneSerializer responseSerializer, + final @Nonnull StoneSerializer errorSerializer) throws DbxWrappedException, DbxException { final byte [] body = writeAsBytes(argSerializer, arg); @@ -135,10 +137,10 @@ public ResT rpcStyle(final String host, headers.add(new HttpRequestor.Header("Content-Type", "application/json; charset=utf-8")); return executeRetriableWithRefresh(requestConfig.getMaxRetries(), new RetriableExecution () { - private String userIdAnon; + private @Nullable String userIdAnon; @Override - public ResT execute() throws DbxWrappedException, DbxException { + public @Nullable ResT execute() throws DbxWrappedException, DbxException { if (!noAuth) { addAuthHeaders(headers); } @@ -161,21 +163,21 @@ public ResT execute() throws DbxWrappedException, DbxException { } } - private RetriableExecution init(String userId){ + private @Nonnull RetriableExecution init(@Nullable String userId){ this.userIdAnon = userId; return this; } }.init(this.userId)); } - public DbxDownloader downloadStyle(final String host, - final String path, - final ArgT arg, + public @Nonnull DbxDownloader downloadStyle(final @Nonnull String host, + final @Nonnull String path, + final @Nullable ArgT arg, final boolean noAuth, - final List extraHeaders, - final StoneSerializer argSerializer, - final StoneSerializer responseSerializer, - final StoneSerializer errorSerializer) + final @Nonnull List extraHeaders, + final @Nonnull StoneSerializer argSerializer, + final @Nonnull StoneSerializer responseSerializer, + final @Nonnull StoneSerializer errorSerializer) throws DbxWrappedException, DbxException { final List headers = new ArrayList(extraHeaders); @@ -190,10 +192,10 @@ public DbxDownloader downloadStyle(final String host, final byte[] body = new byte[0]; return executeRetriableWithRefresh(requestConfig.getMaxRetries(), new RetriableExecution>() { - private String userIdAnon; + private @Nullable String userIdAnon; @Override - public DbxDownloader execute() throws DbxWrappedException, DbxException { + public @Nonnull DbxDownloader execute() throws DbxWrappedException, DbxException { if (!noAuth) { addAuthHeaders(headers); } @@ -232,14 +234,14 @@ public DbxDownloader execute() throws DbxWrappedException, DbxException { } } - private RetriableExecution> init(String userId){ + private @Nonnull RetriableExecution> init(@Nullable String userId){ this.userIdAnon = userId; return this; } }.init(this.userId)); } - private static byte [] writeAsBytes(StoneSerializer serializer, T arg) throws DbxException { + private static @Nonnull byte [] writeAsBytes(@Nonnull StoneSerializer serializer, @Nullable T arg) throws DbxException { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { serializer.serialize(arg, out); @@ -249,7 +251,7 @@ private RetriableExecution> init(String userId){ return out.toByteArray(); } - private static String headerSafeJson(StoneSerializer serializer, T value) { + private static @Nonnull String headerSafeJson(@Nonnull StoneSerializer serializer, @Nullable T value) { StringWriter out = new StringWriter(); try { JsonGenerator g = JSON.createGenerator(out); @@ -264,11 +266,11 @@ private static String headerSafeJson(StoneSerializer serializer, T value) return out.toString(); } - public HttpRequestor.Uploader uploadStyle(String host, - String path, - ArgT arg, + public @Nonnull HttpRequestor.Uploader uploadStyle(@Nonnull String host, + @Nonnull String path, + @Nullable ArgT arg, boolean noAuth, - StoneSerializer argSerializer) + @Nonnull StoneSerializer argSerializer) throws DbxException { String uri = DbxRequestUtil.buildUri(host, path); @@ -295,7 +297,7 @@ public HttpRequestor.Uploader uploadStyle(String host, * * @return configuration to use for issuing requests. */ - public DbxRequestConfig getRequestConfig() { + public @Nonnull DbxRequestConfig getRequestConfig() { return requestConfig; } @@ -304,7 +306,7 @@ public DbxRequestConfig getRequestConfig() { * * @return Dropbox hosts to use for requests. */ - public DbxHost getHost() { + public @Nonnull DbxHost getHost() { return host; } @@ -313,7 +315,7 @@ public DbxHost getHost() { * * @return The user ID of the current Dropbox account. */ - public String getUserId() { + public @Nullable String getUserId() { return userId; } @@ -325,7 +327,7 @@ public String getUserId() { * behavior backwards compatibility in v1, we leave the old implementation in {@code * DbxRequestUtil} unchanged. */ - private static T executeRetriable(int maxRetries, RetriableExecution execution) throws DbxWrappedException, DbxException { + private static @Nullable T executeRetriable(int maxRetries, @Nonnull RetriableExecution execution) throws DbxWrappedException, DbxException { if (maxRetries == 0) { return execution.execute(); } @@ -345,7 +347,7 @@ private static T executeRetriable(int maxRetries, RetriableExecution exec } } - private T executeRetriableWithRefresh(int maxRetries, RetriableExecution + private @Nullable T executeRetriableWithRefresh(int maxRetries, @Nonnull RetriableExecution execution) throws DbxWrappedException, DbxException { try { return executeRetriable(maxRetries, execution); @@ -389,6 +391,6 @@ private static void sleepQuietlyWithJitter(long millis) { } private interface RetriableExecution { - T execute() throws DbxWrappedException, DbxException; + @Nullable T execute() throws DbxWrappedException, DbxException; } } diff --git a/core/src/main/java/com/dropbox/core/v2/DbxTeamClientV2.java b/core/src/main/java/com/dropbox/core/v2/DbxTeamClientV2.java index f2c361eae..d6678ab32 100644 --- a/core/src/main/java/com/dropbox/core/v2/DbxTeamClientV2.java +++ b/core/src/main/java/com/dropbox/core/v2/DbxTeamClientV2.java @@ -12,6 +12,9 @@ import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Use this class to make remote calls to the Dropbox API team endpoints. Team * endpoints expose actions you can perform on or for a Dropbox team. You'll @@ -27,7 +30,7 @@ * in a thread safe {@link HttpRequestor} implementation.

    */ public class DbxTeamClientV2 extends DbxTeamClientV2Base { - private final DbxCredential credential; + private final @Nonnull DbxCredential credential; /** * Creates a client that uses the given OAuth 2 access token as @@ -38,7 +41,7 @@ public class DbxTeamClientV2 extends DbxTeamClientV2Base { * gives your app the ability to make Dropbox API calls. Typically * acquired through {@link com.dropbox.core.DbxWebAuth} */ - public DbxTeamClientV2(DbxRequestConfig requestConfig, String accessToken) { + public DbxTeamClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull String accessToken) { this(requestConfig, accessToken, DbxHost.DEFAULT); } @@ -54,7 +57,7 @@ public DbxTeamClientV2(DbxRequestConfig requestConfig, String accessToken) { * @param host Dropbox hosts to send requests to (used for mocking and * testing) */ - public DbxTeamClientV2(DbxRequestConfig requestConfig, String accessToken, DbxHost host) { + public DbxTeamClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull String accessToken, @Nonnull DbxHost host) { this(requestConfig, accessToken, host, null); } @@ -69,7 +72,7 @@ public DbxTeamClientV2(DbxRequestConfig requestConfig, String accessToken, DbxHo * @param requestConfig Default attributes to use for each request * @param credential The credential object containing all the information for authentication. */ - public DbxTeamClientV2(DbxRequestConfig requestConfig, DbxCredential credential) { + public DbxTeamClientV2(@Nonnull DbxRequestConfig requestConfig, @Nonnull DbxCredential credential) { this(requestConfig, credential, DbxHost.DEFAULT, null); } @@ -86,7 +89,10 @@ public DbxTeamClientV2(DbxRequestConfig requestConfig, DbxCredential credential) * @param userId The user ID of the current Dropbox account. Used for * multi-Dropbox account use-case. */ - public DbxTeamClientV2(DbxRequestConfig requestConfig, String accessToken, DbxHost host, String userId) { + public DbxTeamClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull String accessToken, + @Nonnull DbxHost host, + @Nullable String userId) { this(requestConfig, new DbxCredential(accessToken), host, userId); } @@ -102,8 +108,10 @@ public DbxTeamClientV2(DbxRequestConfig requestConfig, String accessToken, DbxHo * @param userId The user ID of the current Dropbox account. Used for * multi-Dropbox account use-case. */ - public DbxTeamClientV2(DbxRequestConfig requestConfig, DbxCredential credential, DbxHost host, - String userId) { + public DbxTeamClientV2(@Nonnull DbxRequestConfig requestConfig, + @Nonnull DbxCredential credential, + @Nonnull DbxHost host, + @Nullable String userId) { super(new DbxTeamRawClientV2(requestConfig, credential, host, userId, null, null, null)); this.credential = credential; } @@ -118,7 +126,7 @@ public DbxTeamClientV2(DbxRequestConfig requestConfig, DbxCredential credential, * token. * @throws DbxException If refresh failed before of general problems like network issue. */ - public DbxRefreshResult refreshAccessToken() throws DbxException { + public @Nonnull DbxRefreshResult refreshAccessToken() throws DbxException { return this._client.refreshAccessToken(); } @@ -136,7 +144,7 @@ public DbxRefreshResult refreshAccessToken() throws DbxException { * * @throws IllegalArgumentException If {@code memberId} is {@code null} */ - public DbxClientV2 asMember(String memberId) { + public @Nonnull DbxClientV2 asMember(@Nonnull String memberId) { if (memberId == null) { throw new IllegalArgumentException("'memberId' should not be null"); } @@ -167,7 +175,7 @@ public DbxClientV2 asMember(String memberId) { * * @throws IllegalArgumentException If {@code adminId} is {@code null} */ - public DbxClientV2 asAdmin(String adminId) { + public @Nonnull DbxClientV2 asAdmin(@Nonnull String adminId) { if (adminId == null) { throw new IllegalArgumentException("'adminId' should not be null"); } @@ -190,18 +198,18 @@ public DbxClientV2 asAdmin(String adminId) { * to perform requests as a particular team member). */ private static final class DbxTeamRawClientV2 extends DbxRawClientV2 { - private final DbxCredential credential; - private final String memberId; - private final String adminId; + private final @Nonnull DbxCredential credential; + private final @Nullable String memberId; + private final @Nullable String adminId; private DbxTeamRawClientV2( - DbxRequestConfig requestConfig, - DbxCredential credential, - DbxHost host, - String userId, - String memberId, - String adminId, - PathRoot pathRoot) { + @Nonnull DbxRequestConfig requestConfig, + @Nonnull DbxCredential credential, + @Nonnull DbxHost host, + @Nullable String userId, + @Nullable String memberId, + @Nullable String adminId, + @Nullable PathRoot pathRoot) { super(requestConfig, host, userId, pathRoot); if (credential == null) throw new NullPointerException("credential"); @@ -212,7 +220,7 @@ private DbxTeamRawClientV2( } @Override - public DbxRefreshResult refreshAccessToken() throws DbxException { + public @Nonnull DbxRefreshResult refreshAccessToken() throws DbxException { credential.refresh(this.getRequestConfig()); return new DbxRefreshResult(credential.getAccessToken(), (credential.getExpiresAt() - System.currentTimeMillis())/1000); } @@ -228,7 +236,7 @@ public boolean needsRefreshAccessToken() { } @Override - protected void addAuthHeaders(List headers) { + protected void addAuthHeaders(@Nonnull List headers) { DbxRequestUtil.removeAuthHeader(headers); DbxRequestUtil.addAuthHeader(headers, credential.getAccessToken()); if (memberId != null) { @@ -240,7 +248,7 @@ protected void addAuthHeaders(List headers) { } @Override - protected DbxRawClientV2 withPathRoot(PathRoot pathRoot) { + protected @Nonnull DbxRawClientV2 withPathRoot(@Nonnull PathRoot pathRoot) { return new DbxTeamRawClientV2( this.getRequestConfig(), this.credential, diff --git a/core/src/main/java/com/dropbox/core/v2/DbxUploadStyleBuilder.java b/core/src/main/java/com/dropbox/core/v2/DbxUploadStyleBuilder.java index 4a387cfd7..67f25b52d 100644 --- a/core/src/main/java/com/dropbox/core/v2/DbxUploadStyleBuilder.java +++ b/core/src/main/java/com/dropbox/core/v2/DbxUploadStyleBuilder.java @@ -6,6 +6,9 @@ import java.io.IOException; import java.io.InputStream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * The common interface for all builders associated with upload style methods. After setting any * optional request parameters, use {@link #start} or {@link #uploadAndFinish} to initiate the @@ -70,7 +73,7 @@ public abstract class DbxUploadStyleBuilder { * * @throws DbxException if an error occursing initializing the request */ - public abstract DbxUploader start() throws DbxException; + public abstract @Nonnull DbxUploader start() throws DbxException; /** * Convenience method for {@link DbxUploader#uploadAndFinish(InputStream)}: @@ -87,7 +90,7 @@ public abstract class DbxUploadStyleBuilder { * @throws DbxException if an error occurs uploading the data or reading the response * @throws IOException if an error occurs reading the input stream. */ - public R uploadAndFinish(InputStream in) throws X, DbxException, IOException + public @Nullable R uploadAndFinish(@Nonnull InputStream in) throws X, DbxException, IOException { return start().uploadAndFinish(in); } @@ -108,7 +111,7 @@ public R uploadAndFinish(InputStream in) throws X, DbxException, IOException * @throws DbxException if an error occurs uploading the data or reading the response * @throws IOException if an error occurs reading the input stream. */ - public R uploadAndFinish(InputStream in, long limit) throws X, DbxException, IOException + public @Nullable R uploadAndFinish(@Nonnull InputStream in, long limit) throws X, DbxException, IOException { return start().uploadAndFinish(in, limit); } @@ -131,7 +134,9 @@ public R uploadAndFinish(InputStream in, long limit) throws X, DbxException, IOE * @throws DbxException if an error occurs uploading the data or reading the response * @throws IOException if an error occurs reading the input stream. */ - public R uploadAndFinish(InputStream in, long limit, IOUtil.ProgressListener progressListener) + public @Nullable R uploadAndFinish(@Nonnull InputStream in, + long limit, + @Nullable IOUtil.ProgressListener progressListener) throws X, DbxException, IOException { return start().uploadAndFinish(in, limit, progressListener); @@ -154,7 +159,7 @@ public R uploadAndFinish(InputStream in, long limit, IOUtil.ProgressListener pro * @throws DbxException if an error occurs uploading the data or reading the response * @throws IOException if an error occurs reading the input stream. */ - public R uploadAndFinish(InputStream in, IOUtil.ProgressListener progressListener) + public @Nullable R uploadAndFinish(@Nonnull InputStream in, @Nullable IOUtil.ProgressListener progressListener) throws X, DbxException, IOException { return start().uploadAndFinish(in, progressListener); diff --git a/core/src/main/java/com/dropbox/core/v2/callbacks/DbxGlobalCallbackFactory.java b/core/src/main/java/com/dropbox/core/v2/callbacks/DbxGlobalCallbackFactory.java index 2f2a94cc4..472c8f9d6 100644 --- a/core/src/main/java/com/dropbox/core/v2/callbacks/DbxGlobalCallbackFactory.java +++ b/core/src/main/java/com/dropbox/core/v2/callbacks/DbxGlobalCallbackFactory.java @@ -1,5 +1,8 @@ package com.dropbox.core.v2.callbacks; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Client should implement methods in this class to allow for consistent, global handling of route-specific error types, * as well as general network errors. Normally, error handling is done on a request-by-request basis. @@ -10,8 +13,8 @@ */ public interface DbxGlobalCallbackFactory { // Should instantiate separate callback object on each method invocation - DbxRouteErrorCallback createRouteErrorCallback(String userId, T routeError); + @Nullable DbxRouteErrorCallback createRouteErrorCallback(@Nullable String userId, @Nullable T routeError); // Should instantiate separate callback object on each method invocation - DbxNetworkErrorCallback createNetworkErrorCallback(String userId); + @Nonnull DbxNetworkErrorCallback createNetworkErrorCallback(@Nullable String userId); } diff --git a/core/src/main/java/com/dropbox/core/v2/callbacks/DbxNetworkErrorCallback.java b/core/src/main/java/com/dropbox/core/v2/callbacks/DbxNetworkErrorCallback.java index 04f1a709e..9ae8784c6 100644 --- a/core/src/main/java/com/dropbox/core/v2/callbacks/DbxNetworkErrorCallback.java +++ b/core/src/main/java/com/dropbox/core/v2/callbacks/DbxNetworkErrorCallback.java @@ -2,9 +2,11 @@ import com.dropbox.core.DbxException; +import javax.annotation.Nonnull; + /** * Abstract class for network error callback. */ public abstract class DbxNetworkErrorCallback { - public abstract void onNetworkError(DbxException networkError); + public abstract void onNetworkError(@Nonnull DbxException networkError); } diff --git a/core/src/main/java/com/dropbox/core/v2/callbacks/DbxRouteErrorCallback.java b/core/src/main/java/com/dropbox/core/v2/callbacks/DbxRouteErrorCallback.java index 1cf322c1c..fe366634e 100644 --- a/core/src/main/java/com/dropbox/core/v2/callbacks/DbxRouteErrorCallback.java +++ b/core/src/main/java/com/dropbox/core/v2/callbacks/DbxRouteErrorCallback.java @@ -1,16 +1,18 @@ package com.dropbox.core.v2.callbacks; +import javax.annotation.Nullable; + /** * Interface for route error callback. */ public abstract class DbxRouteErrorCallback implements Runnable { - private T routeError = null; + private @Nullable T routeError = null; - public T getRouteError() { + public @Nullable T getRouteError() { return routeError; } - public void setRouteError(T routeError) { + public void setRouteError(@Nullable T routeError) { this.routeError = routeError; } } diff --git a/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxApiWrapper.kt b/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxApiWrapper.kt index ba201d208..460f609dd 100644 --- a/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxApiWrapper.kt +++ b/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxApiWrapper.kt @@ -49,7 +49,9 @@ class DropboxApiWrapper( .uploadBuilder("/$fileName") //Upload to the root of Dropbox .withMode(WriteMode.OVERWRITE) .uploadAndFinish(inputStream) - DropboxUploadApiResponse.Success(fileMetadata) + DropboxUploadApiResponse.Success( + requireNotNull(fileMetadata) { "Upload did not return file metadata." } + ) } catch (exception: DbxException) { DropboxUploadApiResponse.Failure(exception) } @@ -139,7 +141,9 @@ class DropboxApiWrapper( ) .withMode(WriteMode.OVERWRITE) .uploadAndFinish(inputStream) - FileMetadataApiResult.Success(metadata) + FileMetadataApiResult.Success( + requireNotNull(metadata) { "Upload did not return file metadata." } + ) } } catch (e: DbxException) { FileMetadataApiResult.Error(e) @@ -191,4 +195,3 @@ class DropboxApiWrapper( } } - diff --git a/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxCredentialUtil.kt b/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxCredentialUtil.kt index 5562ad89a..dfdcecf6b 100644 --- a/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxCredentialUtil.kt +++ b/examples/android/src/main/java/com/dropbox/core/examples/android/internal/api/DropboxCredentialUtil.kt @@ -14,7 +14,7 @@ class DropboxCredentialUtil(appContext: Context) { ) fun readCredentialLocally(): DbxCredential? { - val serializedCredentialJson = sharedPreferences.getString("credential", null) + val serializedCredentialJson = sharedPreferences.getString("credential", null) ?: return null Log.d(TAG, "Local Credential Value from Shared Preferences: $serializedCredentialJson") return try { DbxCredential.Reader.readFully(serializedCredentialJson) @@ -47,4 +47,4 @@ class DropboxCredentialUtil(appContext: Context) { private companion object { private val TAG = DropboxCredentialUtil::class.java.simpleName } -} \ No newline at end of file +} diff --git a/examples/examples/src/main/java/com/dropbox/core/examples/CredentialsUtil.kt b/examples/examples/src/main/java/com/dropbox/core/examples/CredentialsUtil.kt index 629d51311..34e221e24 100644 --- a/examples/examples/src/main/java/com/dropbox/core/examples/CredentialsUtil.kt +++ b/examples/examples/src/main/java/com/dropbox/core/examples/CredentialsUtil.kt @@ -69,11 +69,15 @@ object CredentialsUtil { private val authOutputFile = File("../../auth_output") fun getDbxCredential(): DbxCredential { - return DbxCredential.Reader.readFromFile(authOutputFile) + return requireNotNull(DbxCredential.Reader.readFromFile(authOutputFile)) { + "Credential file did not contain credentials." + } } fun getAuthInfo(): DbxAuthInfo { - return DbxAuthInfo.Reader.readFromFile(authOutputFile) + return requireNotNull(DbxAuthInfo.Reader.readFromFile(authOutputFile)) { + "Credential file did not contain auth info." + } } } diff --git a/examples/examples/src/main/java/com/dropbox/core/examples/authorize/AuthorizeExample.kt b/examples/examples/src/main/java/com/dropbox/core/examples/authorize/AuthorizeExample.kt index 76b870ffc..a151bd4d6 100644 --- a/examples/examples/src/main/java/com/dropbox/core/examples/authorize/AuthorizeExample.kt +++ b/examples/examples/src/main/java/com/dropbox/core/examples/authorize/AuthorizeExample.kt @@ -59,6 +59,10 @@ object AuthorizeExample { System.err.println("Error reading : " + ex.message) System.exit(1) return + } ?: run { + System.err.println("Error reading : app info file did not contain app info.") + System.exit(1) + return } // Run through Dropbox API authorization process @@ -98,4 +102,4 @@ object AuthorizeExample { return } } -} \ No newline at end of file +} diff --git a/gradle/dropboxJavaSdkLibs.versions.toml b/gradle/dropboxJavaSdkLibs.versions.toml index e98935612..02fd35635 100644 --- a/gradle/dropboxJavaSdkLibs.versions.toml +++ b/gradle/dropboxJavaSdkLibs.versions.toml @@ -60,4 +60,4 @@ blind-pirate-osgi = "com.github.blindpirate.osgi:0.0.6" dependency-guard = { id = "com.dropbox.dependency-guard", version.ref = "dependency-guard" } gradle-version-plugin = "com.github.ben-manes.versions:0.42.0" kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -maven-publish-plugin = "com.vanniktech.maven.publish:0.24.0" \ No newline at end of file +maven-publish-plugin = "com.vanniktech.maven.publish:0.24.0"