Skip to content

Commit

Permalink
Merge pull request #187 from atsign-foundation/exception_handling_cha…
Browse files Browse the repository at this point in the history
…nges

Add AtExceptionStack
  • Loading branch information
sitaram-kalluri authored Jun 3, 2022
2 parents 1a1e4e1 + 23032dc commit 4fd40c0
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 9 deletions.
3 changes: 3 additions & 0 deletions at_commons/lib/at_commons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ export 'package:at_commons/src/at_message.dart';
export 'package:at_commons/src/buffer/at_buffer.dart';
export 'package:at_commons/src/buffer/at_buffer_impl.dart';
export 'package:at_commons/src/compaction/at_compaction_config.dart';
export 'package:at_commons/src/exception/at_client_exceptions.dart';
export 'package:at_commons/src/exception/at_exception_manager.dart';
export 'package:at_commons/src/exception/at_exception_stack.dart';
export 'package:at_commons/src/exception/at_exception_utils.dart';
export 'package:at_commons/src/exception/at_exceptions.dart'
hide
Expand Down
50 changes: 43 additions & 7 deletions at_commons/lib/src/exception/at_client_exceptions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,65 @@ class AtClientException extends AtException {
AtClientException(errorCode, message) : super(message);

/// The named constructor that takes only message
AtClientException.message(message) : super(message);
AtClientException.message(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super(message, intent: intent, exceptionScenario: exceptionScenario);
}

class AtKeyException extends AtClientException {
AtKeyException(message) : super.message(message);
AtKeyException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super.message(message,
intent: intent, exceptionScenario: exceptionScenario);
}

class AtValueException extends AtClientException {
AtValueException(message) : super.message(message);
AtValueException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super.message(message,
intent: intent, exceptionScenario: exceptionScenario);
}

class AtEncryptionException extends AtClientException {
AtEncryptionException(message) : super.message(message);
AtEncryptionException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super.message(message,
intent: intent, exceptionScenario: exceptionScenario);
}

class AtPublicKeyChangeException extends AtEncryptionException {
AtPublicKeyChangeException(message) : super(message);
AtPublicKeyChangeException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super(message, intent: intent, exceptionScenario: exceptionScenario);
}

class AtPublicKeyNotFoundException extends AtEncryptionException {
AtPublicKeyNotFoundException(message) : super(message);
AtPublicKeyNotFoundException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super(message, intent: intent, exceptionScenario: exceptionScenario);
}

class AtDecryptionException extends AtClientException {
AtDecryptionException(message) : super.message(message);
AtDecryptionException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super.message(message,
intent: intent, exceptionScenario: exceptionScenario);
}

class AtPrivateKeyNotFoundException extends AtDecryptionException {
AtPrivateKeyNotFoundException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super(message, intent: intent, exceptionScenario: exceptionScenario);
}

class SharedKeyNotFoundException extends AtDecryptionException {
SharedKeyNotFoundException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super(message, intent: intent, exceptionScenario: exceptionScenario);
}

class SelfKeyNotFoundException extends AtDecryptionException {
SelfKeyNotFoundException(message,
{Intent? intent, ExceptionScenario? exceptionScenario})
: super(message, intent: intent, exceptionScenario: exceptionScenario);
}
15 changes: 15 additions & 0 deletions at_commons/lib/src/exception/at_exception_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:at_commons/at_commons.dart';

/// AtExceptionManager is responsible for creating instances of the appropriate exception
/// classes for a given exception scenario.
class AtExceptionManager {
static AtException createException(AtException atException) {
// If the instance of atException is AtClientException. return as is.
if (atException is AtClientException) {
return atException;
}
// Else wrap the atException into AtClientException and return.
return (AtClientException.message(atException.message))..fromException(atException);

}
}
63 changes: 63 additions & 0 deletions at_commons/lib/src/exception/at_exception_stack.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'dart:collection';

import 'package:at_commons/src/exception/at_exceptions.dart';

/// Class to maintain stack of exceptions to form a chained exception.
class AtExceptionStack implements Comparable<AtChainedException> {
final _exceptionList = Queue<AtChainedException>();

void add(AtChainedException atChainedException) {
if (compareTo(atChainedException) == 0) {
return;
}
_exceptionList.addFirst(atChainedException);
}

/// Concatenate the error messages in the exceptionList and returns a trace message
String getTraceMessage() {
var size = _exceptionList.length;
String fullMessage = '';
fullMessage =
'${getIntentMessage(_exceptionList.first.intent)} caused by\n';
for (AtChainedException element in _exceptionList) {
size--;
fullMessage += element.message;
if (size != 0) {
fullMessage += ' caused by\n';
}
}
return fullMessage;
}

/// Accepts the Intent and returns a message
String getIntentMessage(Intent intent) {
if (intent == Intent.fetchData) {
return 'Failed to fetch data';
}
if (intent == Intent.shareData) {
return 'Failed to share data';
}
if(intent == Intent.decryptData) {
return 'Failed to decrypt the data';
}
return 'Failed to notify data';
}

@override
int compareTo(AtChainedException atChainedException) {
for (var element in _exceptionList) {
if (element.message == atChainedException.message) {
return 0;
}
}
return 1;
}
}

class AtChainedException {
late Intent intent;
late ExceptionScenario exceptionScenario;
late String message;

AtChainedException(this.intent, this.exceptionScenario, this.message);
}
58 changes: 57 additions & 1 deletion at_commons/lib/src/exception/at_exceptions.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:at_commons/src/exception/at_exception_stack.dart';
import 'package:at_commons/src/keystore/at_key.dart';

/// The class [AtException] and its subclasses represents various exceptions that can arise
Expand All @@ -7,12 +8,35 @@ class AtException implements Exception {
/// Represents error message that details the cause of the exception
var message;

AtException(this.message);
Intent? intent;

ExceptionScenario? exceptionScenario;

AtExceptionStack _traceStack = AtExceptionStack();

AtException(this.message, {this.intent, this.exceptionScenario}) {
if (intent != null && exceptionScenario != null) {
_traceStack.add(AtChainedException(intent!, exceptionScenario!, message));
}
}

AtException fromException(AtException atException) {
_traceStack = atException._traceStack;
return atException;
}

@override
String toString() {
return 'Exception: $message';
}

void stack(AtChainedException atChainedException) {
_traceStack.add(atChainedException);
}

String getTraceMessage() {
return _traceStack.getTraceMessage();
}
}

/// The class [AtConnectException] and its subclasses represent any issues that prevents an connection to the root or the secondary server
Expand Down Expand Up @@ -157,3 +181,35 @@ class InvalidRequestException extends AtException {
class InvalidResponseException extends AtException {
InvalidResponseException(message) : super(message);
}

enum ExceptionScenario {
noNetworkConnectivity,
rootServerNotReachable,
secondaryServerNotReachable,
invalidValueProvided,
valueExceedingBufferLimit,
noNamespaceProvided,
invalidKeyFormed,
invalidMetadataProvided,
keyNotFound,
encryptionFailed,
decryptionFailed,
remoteVerbExecutionFailed,
localVerbExecutionFailed,
atSignDoesNotExist,
fetchEncryptionKeys
}

enum Intent {
shareData,
fetchData,
validateKey,
validateAtSign,
remoteVerbExecution,
notifyData,
decryptData,
fetchEncryptionPublicKey,
fetchEncryptionPrivateKey,
fetchEncryptionSharedKey,
fetchSelfEncryptionKey
}
2 changes: 1 addition & 1 deletion at_commons/lib/src/validators/at_key_validation_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class KeyOwnershipValidation extends Validation {
if ((type != KeyType.cachedPublicKey && type != KeyType.cachedSharedKey) &&
owner != atSign) {
return ValidationResult(
'Owner of the key $owner should be same as current @sign atSign');
'Owner of the key $owner should be same as current @sign $atSign');
}
return ValidationResult.noFailure();
}
Expand Down

0 comments on commit 4fd40c0

Please sign in to comment.