Merge pull request #1724 from corda/mnesbit-consistent-custom-exceptions2

Consistent use of CordaException and CordaRuntimeException
This commit is contained in:
Matthew Nesbit 2017-09-29 11:47:00 +01:00 committed by GitHub
commit 1bc9d169ff
24 changed files with 68 additions and 44 deletions

View File

@ -6,6 +6,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.google.common.collect.HashMultimap
import com.google.common.collect.Multimap
import net.corda.client.jackson.StringToMethodCallParser.ParsedMethodCall
import net.corda.core.CordaException
import org.slf4j.LoggerFactory
import java.lang.reflect.Constructor
import java.lang.reflect.Method
@ -146,7 +147,7 @@ open class StringToMethodCallParser<in T : Any> @JvmOverloads constructor(
}
}
open class UnparseableCallException(command: String, cause: Throwable? = null) : Exception("Could not parse as a command: $command", cause) {
open class UnparseableCallException(command: String, cause: Throwable? = null) : CordaException("Could not parse as a command: $command", cause) {
class UnknownMethod(val methodName: String) : UnparseableCallException("Unknown command name: $methodName")
class MissingParameter(methodName: String, val paramName: String, command: String) : UnparseableCallException("Parameter $paramName missing from attempt to invoke $methodName in command: $command")
class TooManyParameters(methodName: String, command: String) : UnparseableCallException("Too many parameters provided for $methodName: $command")

View File

@ -1,10 +1,10 @@
package net.corda.client.rpc
import net.corda.core.CordaRuntimeException
import net.corda.core.serialization.CordaSerializable
/**
* Thrown to indicate that the calling user does not have permission for something they have requested (for example
* calling a method).
*/
@CordaSerializable
class PermissionException(msg: String) : RuntimeException(msg)
class PermissionException(msg: String) : CordaRuntimeException(msg)

View File

@ -15,10 +15,11 @@ interface CordaThrowable {
open class CordaException internal constructor(override var originalExceptionClassName: String? = null,
private var _message: String? = null,
private var _cause: Throwable? = null) : Exception(null, null, true, true), CordaThrowable {
constructor(message: String?,
cause: Throwable?) : this(null, message, cause)
constructor(message: String?) : this(null, message, null)
override val message: String?
get() = if (originalExceptionClassName == null) originalMessage else {
if (originalMessage == null) "$originalExceptionClassName" else "$originalExceptionClassName: $originalMessage"
@ -59,10 +60,12 @@ open class CordaException internal constructor(override var originalExceptionCla
}
open class CordaRuntimeException(override var originalExceptionClassName: String?,
private var _message: String? = null,
private var _cause: Throwable? = null) : RuntimeException(null, null, true, true), CordaThrowable {
private var _message: String?,
private var _cause: Throwable?) : RuntimeException(null, null, true, true), CordaThrowable {
constructor(message: String?, cause: Throwable?) : this(null, message, cause)
constructor(message: String?) : this(null, message, null)
override val message: String?
get() = if (originalExceptionClassName == null) originalMessage else {
if (originalMessage == null) "$originalExceptionClassName" else "$originalExceptionClassName: $originalMessage"

View File

@ -1,11 +1,12 @@
package net.corda.core.crypto
import net.corda.core.CordaException
import net.corda.core.crypto.SecureHash.Companion.zeroHash
import net.corda.core.serialization.CordaSerializable
import java.util.*
@CordaSerializable
class MerkleTreeException(val reason: String) : Exception("Partial Merkle Tree exception. Reason: $reason")
class MerkleTreeException(val reason: String) : CordaException("Partial Merkle Tree exception. Reason: $reason")
/**
* Building and verification of Partial Merkle Tree.

View File

@ -2,6 +2,7 @@ package net.corda.core.internal
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowException
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession
import net.corda.core.serialization.CordaSerializable
@ -63,7 +64,7 @@ class ResolveTransactionsFlow(private val txHashes: Set<SecureHash>,
}
@CordaSerializable
class ExcessivelyLargeTransactionGraph : Exception()
class ExcessivelyLargeTransactionGraph : FlowException()
/** Transaction for fetch attachments for */
private var signedTransaction: SignedTransaction? = null

View File

@ -1,5 +1,6 @@
package net.corda.core.node.services
import net.corda.core.CordaException
import net.corda.core.contracts.PartyAndReference
import net.corda.core.identity.*
import java.security.InvalidAlgorithmParameterException
@ -105,4 +106,4 @@ interface IdentityService {
fun partiesFromName(query: String, exactMatch: Boolean): Set<Party>
}
class UnknownAnonymousPartyException(msg: String) : Exception(msg)
class UnknownAnonymousPartyException(msg: String) : CordaException(msg)

View File

@ -1,7 +1,8 @@
package net.corda.core.serialization
import net.corda.core.CordaException
import net.corda.core.crypto.SecureHash
/** Thrown during deserialisation to indicate that an attachment needed to construct the [WireTransaction] is not found. */
@CordaSerializable
class MissingAttachmentsException(val ids: List<SecureHash>) : Exception()
class MissingAttachmentsException(val ids: List<SecureHash>) : CordaException()

View File

@ -1,5 +1,6 @@
package net.corda.core.transactions
import net.corda.core.CordaException
import net.corda.core.contracts.*
import net.corda.core.crypto.*
import net.corda.core.identity.Party
@ -263,11 +264,11 @@ data class FilteredComponentGroup(override val groupIndex: Int, override val com
* @param reason information about the exception.
*/
@CordaSerializable
class ComponentVisibilityException(val id: SecureHash, val reason: String) : Exception("Component visibility error for transaction with id:$id. Reason: $reason")
class ComponentVisibilityException(val id: SecureHash, val reason: String) : CordaException("Component visibility error for transaction with id:$id. Reason: $reason")
/** Thrown when [FilteredTransaction.verify] fails.
* @param id transaction's id.
* @param reason information about the exception.
*/
@CordaSerializable
class FilteredTransactionVerificationException(val id: SecureHash, val reason: String) : Exception("Transaction with id:$id cannot be verified. Reason: $reason")
class FilteredTransactionVerificationException(val id: SecureHash, val reason: String) : CordaException("Transaction with id:$id cannot be verified. Reason: $reason")

View File

@ -2,6 +2,7 @@ package net.corda.core.transactions
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.TransactionState
import net.corda.core.flows.FlowException
import net.corda.core.serialization.CordaSerializable
/**
@ -11,4 +12,4 @@ import net.corda.core.serialization.CordaSerializable
*/
@CordaSerializable
class MissingContractAttachments(val states: List<TransactionState<ContractState>>)
: Exception("Cannot find contract attachments for ${states.map { it.contract }.distinct() }")
: FlowException("Cannot find contract attachments for ${states.map { it.contract }.distinct() }")

View File

@ -12,6 +12,7 @@ import net.corda.core.contracts.CommandData
import net.corda.core.contracts.LinearState
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.TokenizableAssetInfo
import net.corda.core.flows.FlowException
import net.corda.core.identity.Party
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.TransactionBuilder
@ -199,7 +200,7 @@ enum class Frequency(val annualCompoundCount: Int, val offset: LocalDate.(Long)
@CordaSerializable
open class BusinessCalendar (val holidayDates: List<LocalDate>) {
@CordaSerializable
class UnknownCalendar(name: String) : Exception("$name not found")
class UnknownCalendar(name: String) : FlowException("$name not found")
companion object {
val calendars = listOf("London", "NewYork")

View File

@ -67,7 +67,7 @@ class ThrowableSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<T
logger.warn("Unexpected exception de-serializing throwable: ${proxy.exceptionClass}. Converting to CordaRuntimeException.", e)
}
// If the criteria are not met or we experience an exception constructing the exception, we fall back to our own unchecked exception.
return CordaRuntimeException(proxy.exceptionClass).apply {
return CordaRuntimeException(proxy.exceptionClass, null, null).apply {
this.setMessage(proxy.message)
this.setCause(proxy.cause)
this.stackTrace = proxy.stackTrace

View File

@ -1,11 +1,14 @@
package net.corda.nodeapi.internal.serialization.carpenter
class DuplicateNameException : RuntimeException(
import net.corda.core.CordaException
import net.corda.core.CordaRuntimeException
class DuplicateNameException : CordaRuntimeException(
"An attempt was made to register two classes with the same name within the same ClassCarpenter namespace.")
class InterfaceMismatchException(msg: String) : RuntimeException(msg)
class InterfaceMismatchException(msg: String) : CordaRuntimeException(msg)
class NullablePrimitiveException(msg: String) : RuntimeException(msg)
class NullablePrimitiveException(msg: String) : CordaRuntimeException(msg)
class UncarpentableException(name: String, field: String, type: String) :
Exception("Class $name is loadable yet contains field $field of unknown type $type")
CordaException("Class $name is loadable yet contains field $field of unknown type $type")

View File

@ -6,6 +6,7 @@ import com.google.common.collect.MutableClassToInstanceMap
import com.google.common.util.concurrent.MoreExecutors
import net.corda.confidential.SwapIdentitiesFlow
import net.corda.confidential.SwapIdentitiesHandler
import net.corda.core.CordaException
import net.corda.core.concurrent.CordaFuture
import net.corda.core.cordapp.CordappProvider
import net.corda.core.flows.*
@ -231,7 +232,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
}
}
private class ServiceInstantiationException(cause: Throwable?) : Exception(cause)
private class ServiceInstantiationException(cause: Throwable?) : CordaException("Service Instantiation Error", cause)
private fun installCordaServices() {
cordappProvider.cordapps.flatMap { it.services }.forEach {
@ -465,7 +466,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
}
// Specific class so that MockNode can catch it.
class DatabaseConfigurationException(msg: String) : Exception(msg)
class DatabaseConfigurationException(msg: String) : CordaException(msg)
protected open fun <T> initialiseDatabasePersistence(insideTransaction: () -> T): T {
val props = configuration.dataSourceProperties

View File

@ -1,6 +1,7 @@
package net.corda.node.internal
import com.codahale.metrics.JmxReporter
import net.corda.core.CordaException
import net.corda.core.concurrent.CordaFuture
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
@ -384,6 +385,6 @@ open class Node(override val configuration: FullNodeConfiguration,
}
}
class ConfigurationException(message: String) : Exception(message)
class ConfigurationException(message: String) : CordaException(message)
data class NetworkMapInfo(val address: NetworkHostAndPort, val legalName: CordaX500Name)

View File

@ -1,5 +1,6 @@
package net.corda.node.services.api
import net.corda.core.CordaException
import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowInitiator
@ -62,9 +63,9 @@ interface NetworkMapCacheInternal : NetworkMapCache {
}
@CordaSerializable
sealed class NetworkCacheError : Exception() {
sealed class NetworkCacheException : CordaException("Network Cache Error") {
/** Indicates a failure to deregister, because of a rejected request from the remote node */
class DeregistrationFailed : NetworkCacheError()
class DeregistrationFailed : NetworkCacheException()
}
interface ServiceHubInternal : ServiceHub {

View File

@ -1,5 +1,6 @@
package net.corda.node.services.network
import net.corda.core.CordaException
import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SignedData
import net.corda.core.crypto.isFulfilledBy
@ -189,7 +190,7 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
}
private fun addSubscriber(subscriber: MessageRecipients) {
if (subscriber !is SingleMessageRecipient) throw NodeMapError.InvalidSubscriber()
if (subscriber !is SingleMessageRecipient) throw NodeMapException.InvalidSubscriber()
subscribers.locked {
if (!containsKey(subscriber)) {
put(subscriber, LastAcknowledgeInfo(mapVersion))
@ -198,12 +199,12 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
}
private fun removeSubscriber(subscriber: MessageRecipients) {
if (subscriber !is SingleMessageRecipient) throw NodeMapError.InvalidSubscriber()
if (subscriber !is SingleMessageRecipient) throw NodeMapException.InvalidSubscriber()
subscribers.locked { remove(subscriber) }
}
private fun processAcknowledge(request: UpdateAcknowledge): Unit {
if (request.replyTo !is SingleMessageRecipient) throw NodeMapError.InvalidSubscriber()
if (request.replyTo !is SingleMessageRecipient) throw NodeMapException.InvalidSubscriber()
subscribers.locked {
val lastVersionAcked = this[request.replyTo]?.mapVersion
if ((lastVersionAcked ?: 0) < request.mapVersion) {
@ -360,13 +361,13 @@ class WireNodeRegistration(raw: SerializedBytes<NodeRegistration>, sig: DigitalS
}
@CordaSerializable
sealed class NodeMapError : Exception() {
sealed class NodeMapException : CordaException("Network Map Protocol Error") {
/** Thrown if the signature on the node info does not match the public key for the identity */
class InvalidSignature : NodeMapError()
class InvalidSignature : NodeMapException()
/** Thrown if the replyTo of a subscription change message is not a single message recipient */
class InvalidSubscriber : NodeMapError()
class InvalidSubscriber : NodeMapException()
}
@CordaSerializable

View File

@ -21,7 +21,7 @@ import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.parsePublicKeyBase58
import net.corda.core.utilities.toBase58String
import net.corda.node.services.api.NetworkCacheError
import net.corda.node.services.api.NetworkCacheException
import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.node.services.api.ServiceHubInternal
import net.corda.node.services.messaging.MessagingService
@ -135,7 +135,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
data = NetworkMapService.UpdateAcknowledge(req.mapVersion, network.myAddress).serialize().bytes)
network.send(ackMessage, req.replyTo)
processUpdatePush(req)
} catch (e: NodeMapError) {
} catch (e: NodeMapException) {
logger.warn("Failure during node map update due to bad update: ${e.javaClass.name}")
} catch (e: Exception) {
logger.error("Exception processing update from network map service", e)
@ -202,7 +202,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
val address = getPartyInfo(mapParty)?.let { network.getAddressOfParty(it) } ?:
throw IllegalArgumentException("Can't deregister for updates, don't know the party: $mapParty")
val future = network.sendRequest<SubscribeResponse>(NetworkMapService.SUBSCRIPTION_TOPIC, req, address).map {
if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed()
if (it.confirmed) Unit else throw NetworkCacheException.DeregistrationFailed()
}
_registrationFuture.captureLater(future.map { null })
return future
@ -213,7 +213,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
val reg = req.wireReg.verified()
processRegistration(reg)
} catch (e: SignatureException) {
throw NodeMapError.InvalidSignature()
throw NodeMapException.InvalidSignature()
}
}

View File

@ -6,6 +6,7 @@ import com.google.common.hash.HashCode
import com.google.common.hash.Hashing
import com.google.common.hash.HashingInputStream
import com.google.common.io.CountingInputStream
import net.corda.core.CordaRuntimeException
import net.corda.core.internal.AbstractAttachment
import net.corda.core.contracts.Attachment
import net.corda.core.crypto.SecureHash
@ -58,7 +59,7 @@ class NodeAttachmentService(metrics: MetricRegistry) : AttachmentStorage, Single
}
@CordaSerializable
class HashMismatchException(val expected: SecureHash, val actual: SecureHash) : RuntimeException("File $expected hashed to $actual: corruption in attachment store?")
class HashMismatchException(val expected: SecureHash, val actual: SecureHash) : CordaRuntimeException("File $expected hashed to $actual: corruption in attachment store?")
/**
* Wraps a stream and hashes data as it is read: if the entire stream is consumed, then at the end the hash of

View File

@ -9,6 +9,7 @@ import com.codahale.metrics.Gauge
import com.esotericsoftware.kryo.KryoException
import com.google.common.collect.HashMultimap
import com.google.common.util.concurrent.MoreExecutors
import net.corda.core.CordaException
import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.random63BitValue
@ -641,6 +642,6 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
}
}
class SessionRejectException(val rejectMessage: String, val logMessage: String) : Exception() {
class SessionRejectException(val rejectMessage: String, val logMessage: String) : CordaException(rejectMessage) {
constructor(message: String) : this(message, message)
}

View File

@ -23,6 +23,7 @@ import net.corda.core.messaging.StateMachineUpdate
import net.corda.core.utilities.loggerFor
import net.corda.client.jackson.JacksonSupport
import net.corda.client.jackson.StringToMethodCallParser
import net.corda.core.CordaException
import net.corda.node.internal.Node
import net.corda.node.internal.StartedNode
import net.corda.node.services.messaging.CURRENT_RPC_CONTEXT
@ -258,7 +259,7 @@ object InteractiveShell {
}
}
class NoApplicableConstructor(val errors: List<String>) : Exception() {
class NoApplicableConstructor(val errors: List<String>) : CordaException(this.toString()) {
override fun toString() = (listOf("No applicable constructor for flow. Problems were:") + errors).joinToString(System.lineSeparator())
}

View File

@ -1,5 +1,6 @@
package net.corda.node.utilities.registration
import net.corda.core.CordaException
import net.corda.core.serialization.CordaSerializable
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import java.security.cert.Certificate
@ -14,4 +15,4 @@ interface NetworkRegistrationService {
}
@CordaSerializable
class CertificateRequestException(message: String) : Exception(message)
class CertificateRequestException(message: String) : CordaException(message)

View File

@ -3,6 +3,7 @@ package net.corda.irs.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.crypto.TransactionSignature
import net.corda.core.crypto.isFulfilledBy
import net.corda.core.flows.FlowException
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatingFlow
@ -44,8 +45,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder,
fun tracker(fixName: String) = ProgressTracker(QUERYING(fixName), WORKING, SIGNING)
}
@CordaSerializable
class FixOutOfRange(@Suppress("unused") val byAmount: BigDecimal) : Exception("Fix out of range by $byAmount")
class FixOutOfRange(@Suppress("unused") val byAmount: BigDecimal) : FlowException("Fix out of range by $byAmount")
@CordaSerializable
data class QueryRequest(val queries: List<FixOf>)

View File

@ -9,6 +9,7 @@ import net.corda.client.rpc.CordaRPCClient
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformNode
import net.corda.cordform.NodeDefinition
import net.corda.core.CordaException
import net.corda.core.concurrent.CordaFuture
import net.corda.core.concurrent.firstOf
import net.corda.core.identity.CordaX500Name
@ -411,7 +412,7 @@ fun getTimestampAsDirectoryName(): String {
return DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(UTC).format(Instant.now())
}
class ListenProcessDeathException(hostAndPort: NetworkHostAndPort, listenProcess: Process) : Exception("The process that was expected to listen on $hostAndPort has died with status: ${listenProcess.exitValue()}")
class ListenProcessDeathException(hostAndPort: NetworkHostAndPort, listenProcess: Process) : CordaException("The process that was expected to listen on $hostAndPort has died with status: ${listenProcess.exitValue()}")
/**
* @throws ListenProcessDeathException if [listenProcess] dies before the check succeeds, i.e. the check can't succeed as intended.

View File

@ -4,6 +4,7 @@ import net.corda.core.contracts.*
import net.corda.core.cordapp.CordappProvider
import net.corda.core.crypto.*
import net.corda.core.crypto.NullKeys.NULL_SIGNATURE
import net.corda.core.flows.FlowException
import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import net.corda.core.node.ServiceHub
@ -52,9 +53,9 @@ sealed class EnforceVerifyOrFail {
internal object Token : EnforceVerifyOrFail()
}
class DuplicateOutputLabel(label: String) : Exception("Output label '$label' already used")
class DoubleSpentInputs(ids: List<SecureHash>) : Exception("Transactions spend the same input. Conflicting transactions ids: '$ids'")
class AttachmentResolutionException(attachmentId: SecureHash) : Exception("Attachment with id $attachmentId not found")
class DuplicateOutputLabel(label: String) : FlowException("Output label '$label' already used")
class DoubleSpentInputs(ids: List<SecureHash>) : FlowException("Transactions spend the same input. Conflicting transactions ids: '$ids'")
class AttachmentResolutionException(attachmentId: SecureHash) : FlowException("Attachment with id $attachmentId not found")
/**
* This interpreter builds a transaction, and [TransactionDSL.verifies] that the resolved transaction is correct. Note