diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ActivityHandler.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ActivityHandler.java index 7946e8f7b..f44d4aee0 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ActivityHandler.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ActivityHandler.java @@ -3,6 +3,7 @@ package com.microsoft.bot.builder; +import com.microsoft.bot.connector.Async; import java.net.HttpURLConnection; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -53,17 +54,21 @@ public class ActivityHandler implements Bot { @Override public CompletableFuture onTurn(TurnContext turnContext) { if (turnContext == null) { - throw new IllegalArgumentException("TurnContext cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "TurnContext cannot be null." + )); } if (turnContext.getActivity() == null) { - throw new IllegalArgumentException("turnContext must have a non-null Activity."); + return Async.completeExceptionally(new IllegalArgumentException( + "turnContext must have a non-null Activity." + )); } if (turnContext.getActivity().getType() == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "turnContext.getActivity must have a non-null Type." - ); + )); } switch (turnContext.getActivity().getType()) { diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java index 7a4a4cf55..2d2006e6b 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java @@ -3,6 +3,7 @@ package com.microsoft.bot.builder; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.connector.authentication.ClaimsIdentity; import com.microsoft.bot.schema.Activity; import com.microsoft.bot.schema.ConversationReference; @@ -187,7 +188,9 @@ protected CompletableFuture runPipeline( TurnContext context, BotCallbackHandler callback ) { - BotAssert.contextNotNull(context); + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } // Call any registered Middleware Components looking for ReceiveActivity() if (context.getActivity() != null) { diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java index 012d67fc7..dc07f0ad9 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.microsoft.bot.builder.integration.AdapterIntegration; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.connector.Channels; import com.microsoft.bot.connector.ConnectorClient; import com.microsoft.bot.connector.Conversations; @@ -154,7 +155,6 @@ public BotFrameworkAdapter( RetryStrategy withRetryStrategy, Middleware withMiddleware ) { - this( withCredentialProvider, new AuthenticationConfiguration(), @@ -181,7 +181,6 @@ public BotFrameworkAdapter( RetryStrategy withRetryStrategy, Middleware withMiddleware ) { - if (withCredentialProvider == null) { throw new IllegalArgumentException("CredentialProvider cannot be null"); } @@ -226,7 +225,6 @@ public BotFrameworkAdapter( RetryStrategy withRetryStrategy, Middleware withMiddleware ) { - if (withCredentials == null) { throw new IllegalArgumentException("credentials"); } @@ -287,11 +285,11 @@ public CompletableFuture continueConversation( BotCallbackHandler callback ) { if (reference == null) { - throw new IllegalArgumentException("reference"); + return Async.completeExceptionally(new IllegalArgumentException("reference")); } if (callback == null) { - throw new IllegalArgumentException("callback"); + return Async.completeExceptionally(new IllegalArgumentException("callback")); } botAppId = botAppId == null ? "" : botAppId; @@ -303,7 +301,6 @@ public CompletableFuture continueConversation( claims.put(AuthenticationConstants.APPID_CLAIM, botAppId); ClaimsIdentity claimsIdentity = new ClaimsIdentity("ExternalBearer", claims); - String audience = getBotFrameworkOAuthScope(); return continueConversation(claimsIdentity, reference, audience, callback); @@ -356,19 +353,21 @@ public CompletableFuture continueConversation( BotCallbackHandler callback ) { if (claimsIdentity == null) { - throw new IllegalArgumentException("claimsIdentity"); + return Async.completeExceptionally(new IllegalArgumentException("claimsIdentity")); } if (reference == null) { - throw new IllegalArgumentException("reference"); + return Async.completeExceptionally(new IllegalArgumentException("reference")); } if (callback == null) { - throw new IllegalArgumentException("callback"); + return Async.completeExceptionally(new IllegalArgumentException("callback")); } if (StringUtils.isEmpty(audience)) { - throw new IllegalArgumentException("audience cannot be null or empty"); + return Async.completeExceptionally(new IllegalArgumentException( + "audience cannot be null or empty" + )); } CompletableFuture pipelineResult = new CompletableFuture<>(); @@ -434,7 +433,9 @@ public CompletableFuture processActivity( Activity activity, BotCallbackHandler callback ) { - BotAssert.activityNotNull(activity); + if (activity == null) { + return Async.completeExceptionally(new IllegalArgumentException("Activity")); + } return JwtTokenValidation.authenticateRequest( activity, authHeader, credentialProvider, channelProvider, authConfiguration @@ -460,7 +461,9 @@ public CompletableFuture processActivity( Activity activity, BotCallbackHandler callback ) { - BotAssert.activityNotNull(activity); + if (activity == null) { + return Async.completeExceptionally(new IllegalArgumentException("Activity")); + } CompletableFuture pipelineResult = new CompletableFuture<>(); @@ -552,17 +555,17 @@ public CompletableFuture sendActivities( List activities ) { if (context == null) { - throw new IllegalArgumentException("context"); + return Async.completeExceptionally(new IllegalArgumentException("context")); } if (activities == null) { - throw new IllegalArgumentException("activities"); + return Async.completeExceptionally(new IllegalArgumentException("activities")); } if (activities.size() == 0) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Expecting one or more activities, but the array was empty." - ); + )); } return CompletableFuture.supplyAsync(() -> { @@ -690,15 +693,15 @@ public CompletableFuture deleteConversationMember( String memberId ) { if (context.getActivity().getConversation() == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "BotFrameworkAdapter.deleteConversationMember(): missing conversation" - ); + )); } if (StringUtils.isEmpty(context.getActivity().getConversation().getId())) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "BotFrameworkAdapter.deleteConversationMember(): missing conversation.id" - ); + )); } ConnectorClient connectorClient = context.getTurnState().get(CONNECTOR_CLIENT_KEY); @@ -735,15 +738,15 @@ public CompletableFuture> getActivityMembers( } if (context.getActivity().getConversation() == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "BotFrameworkAdapter.GetActivityMembers(): missing conversation" - ); + )); } if (StringUtils.isEmpty(context.getActivity().getConversation().getId())) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "BotFrameworkAdapter.GetActivityMembers(): missing conversation.id" - ); + )); } ConnectorClient connectorClient = context.getTurnState().get(CONNECTOR_CLIENT_KEY); @@ -760,15 +763,15 @@ public CompletableFuture> getActivityMembers( */ public CompletableFuture> getConversationMembers(TurnContextImpl context) { if (context.getActivity().getConversation() == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "BotFrameworkAdapter.GetActivityMembers(): missing conversation" - ); + )); } if (StringUtils.isEmpty(context.getActivity().getConversation().getId())) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "BotFrameworkAdapter.GetActivityMembers(): missing conversation.id" - ); + )); } ConnectorClient connectorClient = context.getTurnState().get(CONNECTOR_CLIENT_KEY); @@ -823,11 +826,11 @@ public CompletableFuture getConversations( String continuationToken ) { if (StringUtils.isEmpty(serviceUrl)) { - throw new IllegalArgumentException("serviceUrl"); + return Async.completeExceptionally(new IllegalArgumentException("serviceUrl")); } if (credentials == null) { - throw new IllegalArgumentException("credentials"); + return Async.completeExceptionally(new IllegalArgumentException("credentials")); } return getOrCreateConnectorClient(serviceUrl, credentials) @@ -893,28 +896,27 @@ public CompletableFuture getUserToken( String connectionName, String magicCode ) { - BotAssert.contextNotNull(context); - + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } if ( context.getActivity().getFrom() == null || StringUtils.isEmpty(context.getActivity().getFrom().getId()) ) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "BotFrameworkAdapter.getUserToken(): missing from or from.id" - ); + )); } if (StringUtils.isEmpty(connectionName)) { - throw new IllegalArgumentException("connectionName"); + return Async.completeExceptionally(new IllegalArgumentException("connectionName")); } - return createOAuthClient(context, null).thenCompose(oAuthClient -> { - return oAuthClient.getUserToken() - .getToken( - context.getActivity().getFrom().getId(), connectionName, - context.getActivity().getChannelId(), magicCode - ); - }); + return createOAuthClient(context, null).thenCompose(oAuthClient -> oAuthClient.getUserToken() + .getToken( + context.getActivity().getFrom().getId(), connectionName, + context.getActivity().getChannelId(), magicCode + )); } /** @@ -931,9 +933,12 @@ public CompletableFuture getOauthSignInLink( TurnContext context, String connectionName ) { - BotAssert.contextNotNull(context); + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } + if (StringUtils.isEmpty(connectionName)) { - throw new IllegalArgumentException("connectionName"); + return Async.completeExceptionally(new IllegalArgumentException("connectionName")); } return createOAuthClient(context, null).thenCompose(oAuthClient -> { @@ -988,12 +993,14 @@ public CompletableFuture getOauthSignInLink( String userId, String finalRedirect ) { - BotAssert.contextNotNull(context); + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } if (StringUtils.isEmpty(connectionName)) { - throw new IllegalArgumentException("connectionName"); + return Async.completeExceptionally(new IllegalArgumentException("connectionName")); } if (StringUtils.isEmpty(userId)) { - throw new IllegalArgumentException("userId"); + return Async.completeExceptionally(new IllegalArgumentException("userId")); } return createOAuthClient(context, null).thenCompose(oAuthClient -> { @@ -1044,9 +1051,11 @@ public CompletableFuture signOutUser( String connectionName, String userId ) { - BotAssert.contextNotNull(context); + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } if (StringUtils.isEmpty(connectionName)) { - throw new IllegalArgumentException("connectionName"); + return Async.completeExceptionally(new IllegalArgumentException("connectionName")); } return createOAuthClient(context, null).thenCompose(oAuthClient -> { @@ -1075,9 +1084,11 @@ public CompletableFuture> getTokenStatus( String userId, String includeFilter ) { - BotAssert.contextNotNull(context); + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } if (StringUtils.isEmpty(userId)) { - throw new IllegalArgumentException("userId"); + return Async.completeExceptionally(new IllegalArgumentException("userId")); } return createOAuthClient(context, null).thenCompose(oAuthClient -> { @@ -1107,13 +1118,14 @@ public CompletableFuture> getAadTokens( String[] resourceUrls, String userId ) { - BotAssert.contextNotNull(context); + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } if (StringUtils.isEmpty(connectionName)) { - throw new IllegalArgumentException("connectionName"); + return Async.completeExceptionally(new IllegalArgumentException("connectionName")); } - if (resourceUrls == null) { - throw new IllegalArgumentException("resourceUrls"); + return Async.completeExceptionally(new IllegalArgumentException("resourceUrls")); } return createOAuthClient(context, null).thenCompose(oAuthClient -> { @@ -1348,9 +1360,9 @@ private CompletableFuture createConnectorClient( String audience ) { if (claimsIdentity == null) { - throw new UnsupportedOperationException( + return Async.completeExceptionally(new UnsupportedOperationException( "ClaimsIdentity cannot be null. Pass Anonymous ClaimsIdentity if authentication is turned off." - ); + )); } // For requests from channel App Id is in Audience claim of JWT token. For @@ -1477,7 +1489,7 @@ private CompletableFuture getAppCredentials(String appId, String }); } - private String getBotAppId(TurnContext turnContext) { + private String getBotAppId(TurnContext turnContext) throws IllegalStateException { ClaimsIdentity botIdentity = turnContext.getTurnState().get(BOT_IDENTITY_KEY); if (botIdentity == null) { throw new IllegalStateException( diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotState.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotState.java index 9552de981..e0261da7c 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotState.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotState.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.bot.connector.Async; import org.apache.commons.lang3.StringUtils; import java.util.HashMap; @@ -42,8 +43,9 @@ public abstract class BotState implements PropertyManager { * * @param withStorage The storage provider to use. * @param withContextServiceKey The key for the state cache for this BotState. + * @throws IllegalArgumentException Null Storage or empty service key arguments. */ - public BotState(Storage withStorage, String withContextServiceKey) { + public BotState(Storage withStorage, String withContextServiceKey) throws IllegalArgumentException { if (withStorage == null) { throw new IllegalArgumentException("Storage cannot be null"); } @@ -62,8 +64,9 @@ public BotState(Storage withStorage, String withContextServiceKey) { * @param name name of property. * @param type of property. * @return A {@link StatePropertyAccessor} for the property. + * @throws IllegalArgumentException Empty name */ - public StatePropertyAccessor createProperty(String name) { + public StatePropertyAccessor createProperty(String name) throws IllegalArgumentException { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("name cannot be empty"); } @@ -92,24 +95,26 @@ public CompletableFuture load(TurnContext turnContext) { * @return A task that represents the work queued to execute. */ public CompletableFuture load(TurnContext turnContext, boolean force) { - if (turnContext == null) { - throw new IllegalArgumentException("turnContext cannot be null"); - } + return Async.tryCompletable(() -> { + if (turnContext == null) { + throw new IllegalArgumentException("turnContext cannot be null"); + } - CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey); - String storageKey = getStorageKey(turnContext); - if (force || cachedState == null || cachedState.getState() == null) { - return storage.read(new String[] {storageKey}).thenApply(val -> { - turnContext.getTurnState() - .replace( - contextServiceKey, - new CachedBotState((Map) val.get(storageKey)) - ); - return null; - }); - } + CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey); + String storageKey = getStorageKey(turnContext); + if (force || cachedState == null || cachedState.getState() == null) { + return storage.read(new String[]{storageKey}).thenApply(val -> { + turnContext.getTurnState() + .replace( + contextServiceKey, + new CachedBotState((Map) val.get(storageKey)) + ); + return null; + }); + } - return CompletableFuture.completedFuture(null); + return CompletableFuture.completedFuture(null); + }); } /** @@ -132,26 +137,28 @@ public CompletableFuture saveChanges(TurnContext turnContext) { * @return A task that represents the work queued to execute. */ public CompletableFuture saveChanges(TurnContext turnContext, boolean force) { - if (turnContext == null) { - throw new IllegalArgumentException("turnContext cannot be null"); - } + return Async.tryCompletable(() -> { + if (turnContext == null) { + throw new IllegalArgumentException("turnContext cannot be null"); + } - CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey); - if (force || cachedState != null && cachedState.isChanged()) { - String storageKey = getStorageKey(turnContext); - Map changes = new HashMap() { - { - put(storageKey, cachedState.state); - } - }; - - return storage.write(changes).thenApply(val -> { - cachedState.setHash(cachedState.computeHash(cachedState.state)); - return null; - }); - } + CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey); + if (force || cachedState != null && cachedState.isChanged()) { + String storageKey = getStorageKey(turnContext); + Map changes = new HashMap() { + { + put(storageKey, cachedState.state); + } + }; - return CompletableFuture.completedFuture(null); + return storage.write(changes).thenApply(val -> { + cachedState.setHash(cachedState.computeHash(cachedState.state)); + return null; + }); + } + + return CompletableFuture.completedFuture(null); + }); } /** @@ -219,8 +226,9 @@ public JsonNode get(TurnContext turnContext) { * * @param turnContext The context object for this turn. * @return The storage key. + * @throws IllegalArgumentException TurnContext doesn't contain all the required data. */ - public abstract String getStorageKey(TurnContext turnContext); + public abstract String getStorageKey(TurnContext turnContext) throws IllegalArgumentException; /** * Gets the value of a property from the state cache for this BotState. @@ -236,16 +244,22 @@ protected CompletableFuture getPropertyValue( String propertyName ) { if (turnContext == null) { - throw new IllegalArgumentException("turnContext cannot be null"); + return Async.completeExceptionally(new IllegalArgumentException( + "turnContext cannot be null" + )); } if (StringUtils.isEmpty(propertyName)) { - throw new IllegalArgumentException("propertyName cannot be empty"); + return Async.completeExceptionally(new IllegalArgumentException( + "propertyName cannot be empty" + )); } - CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey); - return (CompletableFuture) CompletableFuture - .completedFuture(cachedState.getState().get(propertyName)); + return Async.tryCompletable(() -> { + CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey); + return (CompletableFuture) CompletableFuture + .completedFuture(cachedState.getState().get(propertyName)); + }); } /** diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryStorage.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryStorage.java index 1f2f84d5e..dcf74bafc 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryStorage.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryStorage.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.microsoft.bot.connector.Async; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,7 +84,7 @@ public MemoryStorage(Map values) { @Override public CompletableFuture> read(String[] keys) { if (keys == null) { - throw new IllegalArgumentException("keys cannot be null"); + return Async.completeExceptionally(new IllegalArgumentException("keys cannot be null")); } Map storeItems = new ConcurrentHashMap<>(keys.length); @@ -96,10 +97,10 @@ public CompletableFuture> read(String[] keys) { // Check if type info is set for the class if (!(stateNode.hasNonNull(TYPENAMEFORNONENTITY))) { logger.error("Read failed: Type info not present for " + key); - throw new RuntimeException( + return Async.completeExceptionally(new RuntimeException( String .format("Read failed: Type info not present for key " + key) - ); + )); } String clsName = stateNode.get(TYPENAMEFORNONENTITY).textValue(); @@ -109,18 +110,18 @@ public CompletableFuture> read(String[] keys) { cls = Class.forName(clsName); } catch (ClassNotFoundException e) { logger.error("Read failed: Could not load class {}", clsName); - throw new RuntimeException( + return Async.completeExceptionally(new RuntimeException( String.format("Read failed: Could not load class %s", clsName) - ); + )); } // Populate dictionary storeItems.put(key, objectMapper.treeToValue(stateNode, cls)); } catch (JsonProcessingException e) { logger.error("Read failed: {}", e.toString()); - throw new RuntimeException( + return Async.completeExceptionally(new RuntimeException( String.format("Read failed: %s", e.toString()) - ); + )); } } } @@ -164,13 +165,12 @@ public CompletableFuture write(Map changes) { oldStateETag != null && !StringUtils.equals(newStoreItem.getETag(), "*") && !StringUtils.equals(newStoreItem.getETag(), oldStateETag) ) { - String msg = String.format( "eTag conflict. Original: %s, Current: %s", newStoreItem.getETag(), oldStateETag ); logger.error(msg); - throw new RuntimeException(msg); + return Async.completeExceptionally(new RuntimeException(msg)); } int newTag = eTag++; ((ObjectNode) newState).put("eTag", Integer.toString(newTag)); @@ -192,7 +192,7 @@ public CompletableFuture write(Map changes) { @Override public CompletableFuture delete(String[] keys) { if (keys == null) { - throw new IllegalArgumentException("keys cannot be null"); + return Async.completeExceptionally(new IllegalArgumentException("keys cannot be null")); } synchronized (this.syncroot) { diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java index 224fbf8c5..3bdb35abf 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java @@ -4,6 +4,7 @@ package com.microsoft.bot.builder; import com.codepoetics.protonpack.StreamUtils; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.schema.Activity; import java.time.OffsetDateTime; @@ -49,7 +50,8 @@ public class MemoryTranscriptStore implements TranscriptStore { @Override public final CompletableFuture logActivity(Activity activity) { if (activity == null) { - throw new IllegalArgumentException("activity cannot be null for LogActivity()"); + return Async.completeExceptionally( + new IllegalArgumentException("activity cannot be null for LogActivity()")); } synchronized (sync) { @@ -96,11 +98,13 @@ public CompletableFuture> getTranscriptActivities( OffsetDateTime startDate ) { if (channelId == null) { - throw new IllegalArgumentException(String.format("missing %1$s", "channelId")); + return Async.completeExceptionally( + new IllegalArgumentException(String.format("missing %1$s", "channelId"))); } if (conversationId == null) { - throw new IllegalArgumentException(String.format("missing %1$s", "conversationId")); + return Async.completeExceptionally( + new IllegalArgumentException(String.format("missing %1$s", "conversationId"))); } PagedResult pagedResult = new PagedResult<>(); @@ -147,15 +151,15 @@ public CompletableFuture> getTranscriptActivities( @Override public CompletableFuture deleteTranscript(String channelId, String conversationId) { if (channelId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( String.format("%1$s should not be null", "channelId") - ); + )); } if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( String.format("%1$s should not be null", "conversationId") - ); + )); } synchronized (sync) { @@ -182,7 +186,9 @@ public CompletableFuture> listTranscripts( String continuationToken ) { if (channelId == null) { - throw new IllegalArgumentException(String.format("missing %1$s", "channelId")); + return Async.completeExceptionally(new IllegalArgumentException(String.format( + "missing %1$s", "channelId" + ))); } PagedResult pagedResult = new PagedResult<>(); diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/PrivateConversationState.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/PrivateConversationState.java index 43a35533b..0dc2570c8 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/PrivateConversationState.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/PrivateConversationState.java @@ -26,7 +26,7 @@ public PrivateConversationState(Storage storage) { * @return The storage key. */ @Override - public String getStorageKey(TurnContext turnContext) { + public String getStorageKey(TurnContext turnContext) throws IllegalArgumentException { if (turnContext.getActivity() == null) { throw new IllegalArgumentException("invalid activity"); } diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java index b8804be8e..b0579d519 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java @@ -37,9 +37,10 @@ public class RecognizerResult implements RecognizerConvert { * Return the top scoring intent and its score. * * @return The top scoring intent and score. + * @throws IllegalArgumentException No intents available. */ @JsonIgnore - public IntentScore getTopScoringIntent() { + public IntentScore getTopScoringIntent() throws IllegalArgumentException { if (getIntents() == null) { throw new IllegalArgumentException("RecognizerResult.Intents cannot be null"); } diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ShowTypingMiddleware.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ShowTypingMiddleware.java index 228cf6095..bf490d079 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ShowTypingMiddleware.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ShowTypingMiddleware.java @@ -48,8 +48,9 @@ public ShowTypingMiddleware() { * * @param withDelay Initial delay before sending first typing indicator. * @param withPeriod Rate at which additional typing indicators will be sent. + * @throws IllegalArgumentException delay and period must be greater than zero */ - public ShowTypingMiddleware(long withDelay, long withPeriod) { + public ShowTypingMiddleware(long withDelay, long withPeriod) throws IllegalArgumentException { if (withDelay < 0) { throw new IllegalArgumentException("Delay must be greater than or equal to zero"); } diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TelemetryLoggerMiddleware.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TelemetryLoggerMiddleware.java index df9aa5605..27f8d1e42 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TelemetryLoggerMiddleware.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TelemetryLoggerMiddleware.java @@ -4,6 +4,7 @@ package com.microsoft.bot.builder; import com.fasterxml.jackson.core.JsonProcessingException; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.connector.Channels; import com.microsoft.bot.schema.Activity; import com.microsoft.bot.schema.ActivityTypes; @@ -69,7 +70,9 @@ public BotTelemetryClient getTelemetryClient() { */ @Override public CompletableFuture onTurn(TurnContext context, NextDelegate next) { - BotAssert.contextNotNull(context); + if (context == null) { + return Async.completeExceptionally(new IllegalArgumentException("TurnContext")); + } // log incoming activity at beginning of turn return onReceiveActivity(context.getActivity()).thenCompose(receiveResult -> { diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java index 0b9b26c56..73858a0e5 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.schema.Activity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,7 +39,10 @@ public class TraceTranscriptLogger implements TranscriptLogger { */ @Override public CompletableFuture logActivity(Activity activity) { - BotAssert.activityNotNull(activity); + if (activity == null) { + return Async.completeExceptionally(new IllegalArgumentException("Activity")); + } + String event = null; try { event = mapper.writeValueAsString(activity); diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java index 342439d07..050c311a0 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java @@ -3,6 +3,7 @@ package com.microsoft.bot.builder; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.schema.Activity; import com.microsoft.bot.schema.ActivityTypes; import com.microsoft.bot.schema.ConversationReference; @@ -269,7 +270,7 @@ public CompletableFuture sendActivity( InputHints inputHint ) { if (StringUtils.isEmpty(textReplyToSend)) { - throw new IllegalArgumentException("textReplyToSend"); + return Async.completeExceptionally(new IllegalArgumentException("textReplyToSend")); } Activity activityToSend = new Activity(ActivityTypes.MESSAGE) { @@ -302,7 +303,9 @@ public CompletableFuture sendActivity( */ @Override public CompletableFuture sendActivity(Activity activityToSend) { - BotAssert.activityNotNull(activityToSend); + if (activityToSend == null) { + return Async.completeExceptionally(new IllegalArgumentException("Activity")); + } return sendActivities(Collections.singletonList(activityToSend)) .thenApply(resourceResponses -> { @@ -327,7 +330,7 @@ public CompletableFuture sendActivity(Activity activityToSend) @Override public CompletableFuture sendActivities(List activities) { if (activities == null || activities.size() == 0) { - throw new IllegalArgumentException("activities"); + return Async.completeExceptionally(new IllegalArgumentException("activities")); } // Bind the relevant Conversation Reference properties, such as URLs and @@ -373,7 +376,6 @@ private CompletableFuture sendActivitiesThroughCallbackPipel List activities, int nextCallbackIndex ) { - if (nextCallbackIndex == onSendActivities.size()) { return sendActivitiesThroughAdapter(activities); } @@ -400,7 +402,9 @@ private CompletableFuture sendActivitiesThroughCallbackPipel */ @Override public CompletableFuture updateActivity(Activity withActivity) { - BotAssert.activityNotNull(withActivity); + if (withActivity == null) { + return Async.completeExceptionally(new IllegalArgumentException("Activity")); + } ConversationReference conversationReference = activity.getConversationReference(); withActivity.applyConversationReference(conversationReference); @@ -418,10 +422,11 @@ private CompletableFuture updateActivityInternal( Iterator updateHandlers, Supplier> callAtBottom ) { - - BotAssert.activityNotNull(updateActivity); + if (updateActivity == null) { + return Async.completeExceptionally(new IllegalArgumentException("Activity")); + } if (updateHandlers == null) { - throw new IllegalArgumentException("updateHandlers"); + return Async.completeExceptionally(new IllegalArgumentException("updateHandlers")); } // No middleware to run. @@ -461,7 +466,7 @@ private CompletableFuture updateActivityInternal( */ public CompletableFuture deleteActivity(String activityId) { if (StringUtils.isWhitespace(activityId) || StringUtils.isEmpty(activityId)) { - throw new IllegalArgumentException("activityId"); + return Async.completeExceptionally(new IllegalArgumentException("activityId")); } ConversationReference cr = activity.getConversationReference(); @@ -486,7 +491,7 @@ public CompletableFuture deleteActivity(String activityId) { @Override public CompletableFuture deleteActivity(ConversationReference conversationReference) { if (conversationReference == null) { - throw new IllegalArgumentException("conversationReference"); + return Async.completeExceptionally(new IllegalArgumentException("conversationReference")); } Supplier> actuallyDeleteStuff = () -> getAdapter() @@ -502,9 +507,11 @@ private CompletableFuture deleteActivityInternal( Iterator deleteHandlers, Supplier> callAtBottom ) { - BotAssert.conversationReferenceNotNull(cr); + if (cr == null) { + return Async.completeExceptionally(new IllegalArgumentException("ConversationReference")); + } if (deleteHandlers == null) { - throw new IllegalArgumentException("deleteHandlers"); + return Async.completeExceptionally(new IllegalArgumentException("deleteHandlers")); } // No middleware to run. diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextStateCollection.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextStateCollection.java index 6acda3a1b..c1f5ff73e 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextStateCollection.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextStateCollection.java @@ -26,7 +26,7 @@ public class TurnContextStateCollection implements AutoCloseable { * @return The value. * @throws IllegalArgumentException Null key. */ - public T get(String key) { + public T get(String key) throws IllegalArgumentException { if (key == null) { throw new IllegalArgumentException("key"); } @@ -59,7 +59,7 @@ public T get(Class type) { * @param The type of the value. * @throws IllegalArgumentException For null key or value. */ - public void add(String key, T value) { + public void add(String key, T value) throws IllegalArgumentException { if (key == null) { throw new IllegalArgumentException("key"); } @@ -82,7 +82,7 @@ public void add(String key, T value) { * @param The type of the value. * @throws IllegalArgumentException For null value. */ - public void add(T value) { + public void add(T value) throws IllegalArgumentException { if (value == null) { throw new IllegalArgumentException("value"); } diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java index 950e4f1e7..1aab8bdec 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java @@ -26,7 +26,7 @@ public UserState(Storage withStorage) { * @return The key for the channel and sender. */ @Override - public String getStorageKey(TurnContext turnContext) { + public String getStorageKey(TurnContext turnContext) throws IllegalArgumentException { if (turnContext.getActivity() == null) { throw new IllegalArgumentException("invalid activity"); } diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTests.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTests.java index b5297d69f..6264a05fe 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTests.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTests.java @@ -9,6 +9,7 @@ import com.microsoft.bot.builder.adapters.TestFlow; import com.microsoft.bot.schema.Activity; import com.microsoft.bot.schema.ConversationAccount; +import java.util.concurrent.CompletionException; import org.junit.Assert; import org.junit.Test; @@ -553,7 +554,7 @@ public void State_UseBotStateDirectly() { }).send(Activity.createConversationUpdateActivity()).startTest().join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void UserState_NullChannelIdThrows() { Map dictionary = new HashMap<>(); UserState userState = new UserState(new MemoryStorage(dictionary)); @@ -563,7 +564,7 @@ public void UserState_NullChannelIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void UserState_EmptyChannelIdThrows() { Map dictionary = new HashMap<>(); UserState userState = new UserState(new MemoryStorage(dictionary)); @@ -573,7 +574,7 @@ public void UserState_EmptyChannelIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void UserState_NullFromThrows() { Map dictionary = new HashMap<>(); UserState userState = new UserState(new MemoryStorage(dictionary)); @@ -583,7 +584,7 @@ public void UserState_NullFromThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void UserState_NullFromIdThrows() { Map dictionary = new HashMap<>(); UserState userState = new UserState(new MemoryStorage(dictionary)); @@ -593,7 +594,7 @@ public void UserState_NullFromIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void UserState_EmptyFromIdThrows() { Map dictionary = new HashMap<>(); UserState userState = new UserState(new MemoryStorage(dictionary)); @@ -603,7 +604,7 @@ public void UserState_EmptyFromIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void ConversationState_NullConversationThrows() { Map dictionary = new HashMap<>(); ConversationState conversationState = new ConversationState(new MemoryStorage(dictionary)); @@ -615,7 +616,7 @@ public void ConversationState_NullConversationThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void ConversationState_NullConversationIdThrows() { Map dictionary = new HashMap<>(); ConversationState conversationState = new ConversationState(new MemoryStorage(dictionary)); @@ -627,7 +628,7 @@ public void ConversationState_NullConversationIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void ConversationState_EmptyConversationIdThrows() { Map dictionary = new HashMap<>(); ConversationState conversationState = new ConversationState(new MemoryStorage(dictionary)); @@ -639,7 +640,7 @@ public void ConversationState_EmptyConversationIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void ConversationState_NullChannelIdThrows() { Map dictionary = new HashMap<>(); ConversationState conversationState = new ConversationState(new MemoryStorage(dictionary)); @@ -651,7 +652,7 @@ public void ConversationState_NullChannelIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void ConversationState_EmptyChannelIdThrows() { Map dictionary = new HashMap<>(); ConversationState conversationState = new ConversationState(new MemoryStorage(dictionary)); @@ -663,7 +664,7 @@ public void ConversationState_EmptyChannelIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_NullChannelIdThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( @@ -675,7 +676,7 @@ public void PrivateConversationState_NullChannelIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_EmptyChannelIdThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( @@ -687,7 +688,7 @@ public void PrivateConversationState_EmptyChannelIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_NullFromThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( @@ -699,7 +700,7 @@ public void PrivateConversationState_NullFromThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_NullFromIdThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( @@ -711,7 +712,7 @@ public void PrivateConversationState_NullFromIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_EmptyFromIdThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( @@ -723,7 +724,7 @@ public void PrivateConversationState_EmptyFromIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_NullConversationThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( @@ -735,7 +736,7 @@ public void PrivateConversationState_NullConversationThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_NullConversationIdThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( @@ -747,7 +748,7 @@ public void PrivateConversationState_NullConversationIdThrows() { TestPocoState value = testProperty.get(context).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void PrivateConversationState_EmptyConversationIdThrows() { Map dictionary = new HashMap<>(); PrivateConversationState botState = new PrivateConversationState( diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptBaseTests.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptBaseTests.java index 147ad10ed..08740c97e 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptBaseTests.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptBaseTests.java @@ -6,6 +6,7 @@ import com.microsoft.bot.schema.ActivityTypes; import com.microsoft.bot.schema.ChannelAccount; import com.microsoft.bot.schema.ConversationAccount; +import java.util.concurrent.CompletionException; import org.apache.commons.lang3.StringUtils; import org.junit.Assert; @@ -35,8 +36,8 @@ protected void BadArgs() { try { store.logActivity(null).join(); Assert.fail("logActivity Should have thrown on null"); - } catch (IllegalArgumentException e) { - + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof IllegalArgumentException); } catch (Throwable t) { Assert.fail("logActivity Should have thrown ArgumentNull exception on null"); } @@ -44,8 +45,8 @@ protected void BadArgs() { try { store.getTranscriptActivities(null, null).join(); Assert.fail("getTranscriptActivities Should have thrown on null"); - } catch (IllegalArgumentException e) { - + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof IllegalArgumentException); } catch (Throwable t) { Assert.fail( "getTranscriptActivities Should have thrown ArgumentNull exception on null" @@ -55,8 +56,8 @@ protected void BadArgs() { try { store.getTranscriptActivities("asdfds", null).join(); Assert.fail("getTranscriptActivities Should have thrown on null"); - } catch (IllegalArgumentException e) { - + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof IllegalArgumentException); } catch (Throwable t) { Assert.fail( "getTranscriptActivities Should have thrown ArgumentNull exception on null" @@ -66,8 +67,8 @@ protected void BadArgs() { try { store.listTranscripts(null).join(); Assert.fail("listTranscripts Should have thrown on null"); - } catch (IllegalArgumentException e) { - + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof IllegalArgumentException); } catch (Throwable t) { Assert.fail("listTranscripts Should have thrown ArgumentNull exception on null"); } @@ -75,8 +76,8 @@ protected void BadArgs() { try { store.deleteTranscript(null, null).join(); Assert.fail("deleteTranscript Should have thrown on null channelId"); - } catch (IllegalArgumentException e) { - + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof IllegalArgumentException); } catch (Throwable t) { Assert.fail( "deleteTranscript Should have thrown ArgumentNull exception on null channelId" @@ -86,8 +87,8 @@ protected void BadArgs() { try { store.deleteTranscript("test", null).join(); Assert.fail("deleteTranscript Should have thrown on null conversationId"); - } catch (IllegalArgumentException e) { - + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof IllegalArgumentException); } catch (Throwable t) { Assert.fail( "deleteTranscript Should have thrown ArgumentNull exception on null conversationId" diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Async.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Async.java similarity index 50% rename from libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Async.java rename to libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Async.java index c7b543829..a343cd9b4 100644 --- a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Async.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Async.java @@ -1,53 +1,85 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.integration; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; - -/** - * Asyc and CompletableFuture helpers methods. - */ -public final class Async { - private Async() { - - } - - /** - * Executes a block and throws a completion exception if needed. - * - * @param supplier The block to execute. - * @param The type of the return value. - * @return The return value. - */ - public static T tryThrow(ThrowSupplier supplier) { - try { - return supplier.get(); - } catch (CompletionException ce) { - throw ce; - } catch (Throwable t) { - throw new CompletionException(t); - } - } - - /** - * Executes a block and returns a CompletableFuture with either the return - * value or the exception (completeExceptionally). - * - * @param supplier The block to execute. - * @param The type of the CompletableFuture value. - * @return The CompletableFuture - */ - public static CompletableFuture tryCompletion(ThrowSupplier supplier) { - CompletableFuture result = new CompletableFuture<>(); - - try { - result.complete(supplier.get()); - } catch (Throwable t) { - result.completeExceptionally(t); - } - - return result; - } -} +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +/** + * Asyc and CompletableFuture helpers methods. + */ +public final class Async { + private Async() { + + } + + /** + * Executes a block and throws a completion exception if needed. + * + * @param supplier The block to execute. + * @param The type of the return value. + * @return The return value. + */ + public static T tryThrow(ThrowSupplier supplier) { + try { + return supplier.get(); + } catch (CompletionException ce) { + throw ce; + } catch (Throwable t) { + throw new CompletionException(t); + } + } + + /** + * Executes a block and returns a CompletableFuture with either the return + * value or the exception (completeExceptionally). + * + * @param supplier The block to execute. + * @param The type of the CompletableFuture value. + * @return The CompletableFuture + */ + public static CompletableFuture wrapBlock(ThrowSupplier supplier) { + CompletableFuture result = new CompletableFuture<>(); + + try { + result.complete(supplier.get()); + } catch (Throwable t) { + result.completeExceptionally(t); + } + + return result; + } + + /** + * Executes a block that returns a CompletableFuture, and catches any exceptions in order + * to properly return a completed exceptionally result. + * + * @param supplier The block to execute. + * @param The type of the CompletableFuture value. + * @return The CompletableFuture + */ + public static CompletableFuture tryCompletable(ThrowSupplier> supplier) { + CompletableFuture result = new CompletableFuture<>(); + + try { + return supplier.get(); + } catch (Throwable t) { + result.completeExceptionally(t); + } + + return result; + } + + /** + * Constructs a CompletableFuture completed exceptionally. + * @param ex The exception. + * @param Type of CompletableFuture. + * @return A CompletableFuture with the exception. + */ + public static CompletableFuture completeExceptionally(Throwable ex) { + CompletableFuture result = new CompletableFuture<>(); + result.completeExceptionally(ex); + return result; + } +} diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ThrowSupplier.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ThrowSupplier.java similarity index 87% rename from libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ThrowSupplier.java rename to libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ThrowSupplier.java index 1696c0808..9e8141f44 100644 --- a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ThrowSupplier.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ThrowSupplier.java @@ -1,19 +1,19 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.integration; - -/** - * A Supplier that throws. - * @param The type of the Supplier return value. - */ -@FunctionalInterface -public interface ThrowSupplier { - /** - * Gets a result. - * - * @return a result - * @throws Throwable Any exception - */ - T get() throws Throwable; -} +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector; + +/** + * A Supplier that throws. + * @param The type of the Supplier return value. + */ +@FunctionalInterface +public interface ThrowSupplier { + /** + * Gets a result. + * + * @return a result + * @throws Throwable Any exception + */ + T get() throws Throwable; +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java index 74870aa0d..fe9dffabc 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java @@ -38,8 +38,10 @@ public abstract class EndorsementsValidator { * endorsement list, or the incoming activity is not * considered valid. * @return True is the expected endorsement is found in the Endorsement set. + * @throws IllegalArgumentException Missing endorsements */ - public static boolean validate(String expectedEndorsement, List endorsements) { + public static boolean validate(String expectedEndorsement, List endorsements) + throws IllegalArgumentException { // If the Activity came in and doesn't have a Channel ID then it's making no // assertions as to who endorses it. This means it should pass. diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java index 454b719bd..084f9c43b 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java @@ -3,6 +3,7 @@ package com.microsoft.bot.connector.authentication; +import com.microsoft.bot.connector.Async; import org.apache.commons.lang3.StringUtils; import java.time.Duration; @@ -79,8 +80,6 @@ public static CompletableFuture authenticateToken( * @param channelId The ID of the channel to validate. * @param authConfig The authentication configuration. * @return A valid ClaimsIdentity. - * - * On join: * @throws AuthenticationException A token issued by the Bot Framework will FAIL * this check. Only Emulator tokens will pass. */ @@ -93,7 +92,7 @@ public static CompletableFuture authenticateToken( AuthenticationConfiguration authConfig ) { if (authConfig == null) { - throw new IllegalArgumentException("Missing AuthenticationConfiguration"); + return Async.completeExceptionally(new IllegalArgumentException("Missing AuthenticationConfiguration")); } return channelProvider.getChannelService() diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java index 3b6e5303e..71f52d511 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java @@ -3,6 +3,7 @@ package com.microsoft.bot.connector.authentication; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.schema.Activity; import java.util.Map; import org.apache.commons.lang3.StringUtils; @@ -130,11 +131,7 @@ public static CompletableFuture validateAuthHeader( * @param serviceUrl The service URL for the activity. * @param authConfig The authentication configuration. * @return A task that represents the work queued to execute. - * - * On Call: * @throws IllegalArgumentException Incorrect arguments supplied - * - * On Join: * @throws AuthenticationException Authentication Error */ public static CompletableFuture validateAuthHeader( @@ -146,7 +143,8 @@ public static CompletableFuture validateAuthHeader( AuthenticationConfiguration authConfig ) { if (StringUtils.isEmpty(authHeader)) { - throw new IllegalArgumentException("No authHeader present. Auth is required."); + return Async.completeExceptionally( + new IllegalArgumentException("No authHeader present. Auth is required.")); } boolean usingEmulator = EmulatorValidation.isTokenFromEmulator(authHeader); @@ -183,8 +181,9 @@ public static CompletableFuture validateAuthHeader( * @param claims The map of claims. * @return The value of the appId claim if found (null if it can't find a * suitable claim). + * @throws IllegalArgumentException Missing claims */ - public static String getAppIdFromClaims(Map claims) { + public static String getAppIdFromClaims(Map claims) throws IllegalArgumentException { if (claims == null) { throw new IllegalArgumentException("claims"); } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java index ed713763e..0ff583ac9 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java @@ -6,6 +6,7 @@ package com.microsoft.bot.connector.rest; +import com.microsoft.bot.connector.Async; import retrofit2.Retrofit; import com.microsoft.bot.connector.Attachments; import com.google.common.reflect.TypeToken; @@ -84,9 +85,9 @@ CompletableFuture> getAttachment( */ public CompletableFuture getAttachmentInfo(String attachmentId) { if (attachmentId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter attachmentId is required and cannot be null." - ); + )); } return service.getAttachmentInfo( @@ -125,13 +126,16 @@ private ServiceResponse getAttachmentInfoDelegate( */ public CompletableFuture getAttachment(String attachmentId, String viewId) { if (attachmentId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter attachmentId is required and cannot be null." - ); + )); } if (viewId == null) { - throw new IllegalArgumentException("Parameter viewId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter viewId is required and cannot be null." + )); } + return service.getAttachment( attachmentId, viewId, this.client.getAcceptLanguage(), this.client.getUserAgent() ).thenApply(responseBodyResponse -> { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestBotSignIn.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestBotSignIn.java index 9628de4e9..742b48623 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestBotSignIn.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestBotSignIn.java @@ -6,6 +6,7 @@ package com.microsoft.bot.connector.rest; +import com.microsoft.bot.connector.Async; import retrofit2.Retrofit; import com.microsoft.bot.connector.BotSignIn; import com.microsoft.bot.restclient.ServiceResponse; @@ -65,8 +66,11 @@ CompletableFuture> getSignInUrl( */ public CompletableFuture getSignInUrl(String state) { if (state == null) { - throw new IllegalArgumentException("Parameter state is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter state is required and cannot be null." + )); } + final String codeChallenge = null; final String emulatorUrl = null; final String finalRedirect = null; @@ -98,8 +102,11 @@ public CompletableFuture getSignInUrl( String finalRedirect ) { if (state == null) { - throw new IllegalArgumentException("Parameter state is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter state is required and cannot be null." + )); } + return service.getSignInUrl(state, codeChallenge, emulatorUrl, finalRedirect) .thenApply(responseBodyResponse -> { try { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java index ce39d99c3..14600a500 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java @@ -6,6 +6,7 @@ package com.microsoft.bot.connector.rest; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.restclient.ServiceResponseBuilder; import com.microsoft.bot.schema.Activity; import com.microsoft.bot.schema.AttachmentData; @@ -263,9 +264,9 @@ public CompletableFuture createConversation( ConversationParameters parameters ) { if (parameters == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter parameters is required and cannot be null." - ); + )); } Validator.validate(parameters); @@ -319,14 +320,14 @@ public CompletableFuture sendToConversation( Activity activity ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (activity == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter activity is required and cannot be null." - ); + )); } Validator.validate(activity); @@ -372,35 +373,39 @@ public CompletableFuture updateActivity( Activity activity ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (activityId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter activityId is required and cannot be null." - ); + )); } if (activity == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter activity is required and cannot be null." - ); + )); } - Validator.validate(activity); - return service.updateActivity( - conversationId, activityId, activity, client.getAcceptLanguage(), client.getUserAgent() - ) + return Async.tryCompletable(() -> { + Validator.validate(activity); + return service.updateActivity( + conversationId, activityId, activity, client.getAcceptLanguage(), + client.getUserAgent() + ) - .thenApply(responseBodyResponse -> { - try { - return updateActivityDelegate(responseBodyResponse).body(); - } catch (ErrorResponseException e) { - throw e; - } catch (Throwable t) { - throw new ErrorResponseException("updateActivityAsync", responseBodyResponse); - } - }); + .thenApply(responseBodyResponse -> { + try { + return updateActivityDelegate(responseBodyResponse).body(); + } catch (ErrorResponseException e) { + throw e; + } catch (Throwable t) { + throw new ErrorResponseException( + "updateActivityAsync", responseBodyResponse); + } + }); + }); } private ServiceResponse updateActivityDelegate( @@ -432,19 +437,19 @@ public CompletableFuture replyToActivity( Activity activity ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (activityId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter activityId is required and cannot be null." - ); + )); } if (activity == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter activity is required and cannot be null." - ); + )); } Validator.validate(activity); @@ -488,14 +493,14 @@ private ServiceResponse replyToActivityDelegate( @Override public CompletableFuture deleteActivity(String conversationId, String activityId) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (activityId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter activityId is required and cannot be null." - ); + )); } return service.deleteActivity( @@ -534,9 +539,9 @@ private ServiceResponse deleteActivityDelegate( @Override public CompletableFuture> getConversationMembers(String conversationId) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } return service.getConversationMembers( @@ -579,12 +584,14 @@ public CompletableFuture getConversationMember( String conversationId ) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } return service.getConversationMember( @@ -628,14 +635,14 @@ public CompletableFuture deleteConversationMember( String memberId ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (memberId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter memberId is required and cannot be null." - ); + )); } return service.deleteConversationMember( @@ -682,14 +689,14 @@ public CompletableFuture> getActivityMembers( String activityId ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (activityId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter activityId is required and cannot be null." - ); + )); } return service.getActivityMembers( @@ -729,14 +736,14 @@ public CompletableFuture uploadAttachment( AttachmentData attachmentUpload ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (attachmentUpload == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter attachmentUpload is required and cannot be null." - ); + )); } Validator.validate(attachmentUpload); @@ -783,12 +790,14 @@ public CompletableFuture sendConversationHistory( Transcript history ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (history == null) { - throw new IllegalArgumentException("Parameter history is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter history is required and cannot be null." + )); } Validator.validate(history); @@ -837,9 +846,9 @@ public CompletableFuture getConversationPagedMembers( String conversationId ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } return service.getConversationPagedMembers( @@ -889,14 +898,14 @@ public CompletableFuture getConversationPagedMembers( String continuationToken ) { if (conversationId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter conversationId is required and cannot be null." - ); + )); } if (continuationToken == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter continuationToken is required and cannot be null." - ); + )); } return service.getConversationPagedMembers( diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestTeamsOperations.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestTeamsOperations.java index b3a96346a..89f5a7d1f 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestTeamsOperations.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestTeamsOperations.java @@ -7,6 +7,7 @@ package com.microsoft.bot.connector.rest; import com.google.common.reflect.TypeToken; +import com.microsoft.bot.connector.Async; import com.microsoft.bot.connector.teams.TeamsOperations; import com.microsoft.bot.restclient.ServiceResponse; import com.microsoft.bot.schema.teams.ConversationList; @@ -56,7 +57,9 @@ public class RestTeamsOperations implements TeamsOperations { @Override public CompletableFuture fetchChannelList(String teamId) { if (teamId == null) { - throw new IllegalArgumentException("Parameter teamId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter teamId is required and cannot be null." + )); } return service.fetchChannelList(teamId, client.getAcceptLanguage(), client.getUserAgent()) @@ -92,7 +95,9 @@ private ServiceResponse fetchChannelListDelegate( @Override public CompletableFuture fetchTeamDetails(String teamId) { if (teamId == null) { - throw new IllegalArgumentException("Parameter teamId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter teamId is required and cannot be null." + )); } return service.fetchTeamDetails(teamId, client.getAcceptLanguage(), client.getUserAgent()) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestUserToken.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestUserToken.java index b79504d65..40821b4a0 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestUserToken.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestUserToken.java @@ -6,6 +6,7 @@ package com.microsoft.bot.connector.rest; +import com.microsoft.bot.connector.Async; import retrofit2.Retrofit; import com.microsoft.bot.connector.UserToken; import com.google.common.reflect.TypeToken; @@ -111,13 +112,16 @@ CompletableFuture> getTokenStatus( @Override public CompletableFuture getToken(String userId, String connectionName) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } if (connectionName == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter connectionName is required and cannot be null." - ); + )); } + final String channelId = null; final String code = null; return service.getToken(userId, connectionName, channelId, code) @@ -149,13 +153,16 @@ public CompletableFuture getToken( String code ) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } if (connectionName == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter connectionName is required and cannot be null." - ); + )); } + return service.getToken(userId, connectionName, channelId, code) .thenApply(responseBodyResponse -> { try { @@ -199,18 +206,21 @@ public CompletableFuture> getAadTokens( AadResourceUrls aadResourceUrls ) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } if (connectionName == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter connectionName is required and cannot be null." - ); + )); } if (aadResourceUrls == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter aadResourceUrls is required and cannot be null." - ); + )); } + Validator.validate(aadResourceUrls); final String channelId = null; return service.getAadTokens(userId, connectionName, aadResourceUrls, channelId) @@ -242,29 +252,35 @@ public CompletableFuture> getAadTokens( String channelId ) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } if (connectionName == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter connectionName is required and cannot be null." - ); + )); } if (aadResourceUrls == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter aadResourceUrls is required and cannot be null." - ); + )); } - Validator.validate(aadResourceUrls); - return service.getAadTokens(userId, connectionName, aadResourceUrls, channelId) - .thenApply(responseBodyResponse -> { - try { - return getAadTokensDelegate(responseBodyResponse).body(); - } catch (ErrorResponseException e) { - throw e; - } catch (Throwable t) { - throw new ErrorResponseException("getAadTokens", responseBodyResponse); - } - }); + + return Async.tryCompletable(() -> { + Validator.validate(aadResourceUrls); + return service.getAadTokens(userId, connectionName, aadResourceUrls, channelId) + .thenApply(responseBodyResponse -> { + try { + return getAadTokensDelegate(responseBodyResponse).body(); + } catch (ErrorResponseException e) { + throw e; + } catch (Throwable t) { + throw new ErrorResponseException("getAadTokens", responseBodyResponse); + } + + }); + }); } private ServiceResponse> getAadTokensDelegate( @@ -292,7 +308,9 @@ private ServiceResponse> getAadTokensDelegate( @Override public CompletableFuture signOut(String userId) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } return service.signOut(userId).thenApply(responseBodyResponse -> { @@ -321,17 +339,19 @@ public CompletableFuture signOut( String channelId ) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } if (connectionName == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter connectionName is required and cannot be null." - ); + )); } if (channelId == null) { - throw new IllegalArgumentException( + return Async.completeExceptionally(new IllegalArgumentException( "Parameter channelId is required and cannot be null." - ); + )); } return service.signOut(userId, connectionName, channelId) @@ -371,8 +391,11 @@ private ServiceResponse signOutDelegate( @Override public CompletableFuture> getTokenStatus(String userId) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } + final String channelId = null; final String include = null; return service.getTokenStatus(userId, channelId, include) @@ -402,8 +425,11 @@ public CompletableFuture> getTokenStatus( String include ) { if (userId == null) { - throw new IllegalArgumentException("Parameter userId is required and cannot be null."); + return Async.completeExceptionally(new IllegalArgumentException( + "Parameter userId is required and cannot be null." + )); } + return service.getTokenStatus(userId, channelId, include) .thenApply(responseBodyResponse -> { try { diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java index 11457670c..9902d8633 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java @@ -123,8 +123,8 @@ public void CreateConversationWithNullParameter() { try { ConversationResourceResponse result = connector.getConversations().createConversation(null).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -178,8 +178,8 @@ public void GetConversationMembersWithNullConversationId() { try { List members = connector.getConversations().getConversationMembers(null).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -328,20 +328,20 @@ public void SendToConversationWithNullConversationId() { }}; try { - connector.getConversations().sendToConversation(null, activity); + connector.getConversations().sendToConversation(null, activity).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @Test public void SendToConversationWithNullActivity() { try { - connector.getConversations().sendToConversation("id",null); + connector.getConversations().sendToConversation("id",null).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -452,20 +452,20 @@ public void GetActivityMembersWithInvalidConversationId() { @Test public void GetActivityMembersWithNullConversationId() { try { - connector.getConversations().getActivityMembers(null, "id"); + connector.getConversations().getActivityMembers(null, "id").join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @Test public void GetActivityMembersWithNullActivityId() { try { - connector.getConversations().getActivityMembers("id", null); + connector.getConversations().getActivityMembers("id", null).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -544,10 +544,10 @@ public void ReplyToActivityWithNullConversationId() { }}; try { - connector.getConversations().replyToActivity(null, "id", activity); + connector.getConversations().replyToActivity(null, "id", activity).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -560,20 +560,20 @@ public void ReplyToActivityWithNullActivityId() { }}; try { - connector.getConversations().replyToActivity("id", null, activity); + connector.getConversations().replyToActivity("id", null, activity).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @Test public void ReplyToActivityWithNullActivity() { try { - connector.getConversations().replyToActivity("id", "id", null); + connector.getConversations().replyToActivity("id", "id", null).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -597,8 +597,8 @@ public void ReplyToActivityWithNullReply() { try { ResourceResponse replyResponse = connector.getConversations().replyToActivity(conversation.getId(), response.getId(), null).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -659,8 +659,8 @@ public void DeleteActivityWithNullConversationId() { try { connector.getConversations().deleteActivity(null, "id").join(); Assert.fail("expected exception did not occur."); - } catch(IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch(CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -669,8 +669,8 @@ public void DeleteActivityWithNullActivityId() { try { connector.getConversations().deleteActivity("id", null).join(); Assert.fail("expected exception did not occur."); - } catch(IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch(CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -743,10 +743,10 @@ public void UpdateActivityWithNullConversationId() { }}; try { - connector.getConversations().updateActivity(null, "id", activity); + connector.getConversations().updateActivity(null, "id", activity).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @@ -759,20 +759,20 @@ public void UpdateActivityWithNullActivityId() { }}; try { - connector.getConversations().updateActivity("id", null, activity); + connector.getConversations().updateActivity("id", null, activity).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } @Test public void UpdateActivityWithNullActivity() { try { - connector.getConversations().updateActivity("id", "id", null); + connector.getConversations().updateActivity("id", "id", null).join(); Assert.fail("expected exception did not occur."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("cannot be null")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("cannot be null")); } } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index 45db7c97a..ce755c5a4 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -98,8 +98,8 @@ public void EmptyHeaderBotWithNoCredentialsShouldThrow() throws ExecutionExcepti "", null).join(); Assert.fail("Should have thrown IllegalArgumentException"); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("authHeader")); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause().getMessage().contains("authHeader")); } } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTests.java index 23fd4b6cf..75fbd1c98 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTests.java @@ -4,6 +4,7 @@ import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.connector.rest.RestOAuthClient; import com.microsoft.bot.schema.AadResourceUrls; +import java.util.concurrent.CompletionException; import org.junit.Assert; import org.junit.Test; @@ -35,7 +36,7 @@ public void OAuthClient_ShouldThrowOnNullCredentials() { OAuthClient client = new RestOAuthClient("http://localhost", null); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void GetUserToken_ShouldThrowOnEmptyConnectionName() { OAuthClient client = new RestOAuthClient("http://localhost", new BotAccessTokenStub("token")); client.getUserToken().getToken("userid", null).join(); @@ -52,40 +53,40 @@ public void GetUserToken_ShouldReturnNullOnInvalidConnectionstring() { }).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void SignOutUser_ShouldThrowOnEmptyUserId() { OAuthClient client = new RestOAuthClient("http://localhost", new BotAccessTokenStub("token")); - client.getUserToken().signOut(null); + client.getUserToken().signOut(null).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void GetSigninLink_ShouldThrowOnNullState() { OAuthClient client = new RestOAuthClient("http://localhost", new BotAccessTokenStub("token")); - client.getBotSignIn().getSignInUrl(null); + client.getBotSignIn().getSignInUrl(null).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void GetTokenStatus_ShouldThrowOnNullUserId() { OAuthClient client = new RestOAuthClient("http://localhost", new BotAccessTokenStub("token")); - client.getUserToken().getTokenStatus(null); + client.getUserToken().getTokenStatus(null).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void GetAadTokensAsync_ShouldThrowOnNullUserId() { OAuthClient client = new RestOAuthClient("http://localhost", new BotAccessTokenStub("token")); - client.getUserToken().getAadTokens(null, "connection", new AadResourceUrls()); + client.getUserToken().getAadTokens(null, "connection", new AadResourceUrls()).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void GetAadTokensAsync_ShouldThrowOnNullConncetionName() { OAuthClient client = new RestOAuthClient("http://localhost", new BotAccessTokenStub("token")); - client.getUserToken().getAadTokens("user", null, new AadResourceUrls()); + client.getUserToken().getAadTokens("user", null, new AadResourceUrls()).join(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = CompletionException.class) public void GetAadTokensAsync_ShouldThrowOnNullResourceUrls() { OAuthClient client = new RestOAuthClient("http://localhost", new BotAccessTokenStub("token")); - client.getUserToken().getAadTokens("user", "connection", null); + client.getUserToken().getAadTokens("user", "connection", null).join(); } } diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java index d6b36780f..11848f35d 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java @@ -170,9 +170,10 @@ public static T getAs( * @param obj of type T * @param The type of the value. * @return This Entity with the properties from the passed sub-Entity. + * @throws IllegalArgumentException For arguments that can't be converted. */ @JsonIgnore - public Entity setAs(T obj) { + public Entity setAs(T obj) throws IllegalArgumentException { // Serialize String tempJson; try {