summaryrefslogtreecommitdiffstats
path: root/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java
diff options
context:
space:
mode:
Diffstat (limited to 'container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java')
-rw-r--r--container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java217
1 files changed, 217 insertions, 0 deletions
diff --git a/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java b/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java
new file mode 100644
index 00000000000..0ced664bfdc
--- /dev/null
+++ b/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java
@@ -0,0 +1,217 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.processing.request;
+
+/**
+ * An error encountered while processing a request.
+ * This can be subclassed to add error messages containing more information.
+ * <p>
+ * Error messages are immutable.
+ *
+ * @author bratseth
+ */
+public class ErrorMessage implements Cloneable {
+
+ private final int code;
+ private final String message;
+ private final String detailedMessage;
+ private final Throwable cause;
+
+ /**
+ * Creates an error
+ *
+ * @param message the textual message describing this condition tersely
+ */
+ public ErrorMessage(String message) {
+ this(0, message, null, null);
+ }
+
+ /**
+ * Creates an error
+ *
+ * @param message the textual message describing this condition tersely
+ * @param code an error code. If this is bound to HTTP request/responses and
+ * this error code is a HTTP status code, this code will be returned as the HTTP status
+ */
+ public ErrorMessage(int code, String message) {
+ this(code, message, null, null);
+ }
+
+ /**
+ * Creates an error
+ *
+ * @param message the textual message describing this condition tersely
+ * @param details a longer detail description of this condition
+ */
+ public ErrorMessage(String message, String details) {
+ this(0, message, details, null);
+ }
+
+ /**
+ * Creates an error
+ *
+ * @param message the textual message describing this condition tersely
+ * @param code an error code. If this is bound to HTTP request/responses and
+ * this error code is a HTTP status code, this code will be returned as the HTTP status
+ * @param details a longer detail description of this condition
+ */
+ public ErrorMessage(int code, String message, String details) {
+ this(code, message, details, null);
+ }
+
+ /**
+ * Creates an error
+ *
+ * @param message the textual message describing this condition tersely
+ * @param cause the cause of this error
+ */
+ public ErrorMessage(String message, Throwable cause) {
+ this(0, message, null, cause);
+ }
+
+ /**
+ * Creates an error
+ *
+ * @param code an error code. If this is bound to HTTP request/responses and
+ * this error code is a HTTP status code, this code will be returned as the HTTP status
+ * @param message the textual message describing this condition tersely
+ * @param cause the cause of this error
+ */
+ public ErrorMessage(int code, String message, Throwable cause) {
+ this(code, message, null, cause);
+ }
+
+ /**
+ * Creates an error
+ *
+ * @param message the textual message describing this condition tersely
+ * @param details a longer detail description of this condition
+ * @param cause the cause of this error
+ */
+ public ErrorMessage(String message, String details, Throwable cause) {
+ this(0, message, details, cause);
+ }
+
+ /**
+ * Creates an error
+ *
+ * @param code an error code. If this is bound to HTTP request/responses and
+ * this error code is a HTTP status code, this code will be returned as the HTTP status
+ * @param message the textual message describing this condition tersely
+ * @param details a longer detail description of this condition
+ * @param cause the cause of this error
+ */
+ public ErrorMessage(int code, String message, String details, Throwable cause) {
+ if (message == null) throw new NullPointerException("Message cannot be null");
+ this.code = code;
+ this.message = message;
+ this.detailedMessage = details;
+ this.cause = cause;
+ }
+
+ /**
+ * Returns the code of this message, or 0 if no code is set
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /**
+ * Returns the error message, never null
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * Returns detailed information about this error, or null if there is no detailed message
+ */
+ public String getDetailedMessage() {
+ return detailedMessage;
+ }
+
+ /**
+ * Returns the throwable associated with this error, or null if none
+ */
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns a formatted message containing the information in this
+ */
+ @Override
+ public String toString() {
+ if (code == 0 && detailedMessage == null && cause == null) return message; // shortcut
+ StringBuilder b = new StringBuilder();
+ if (code != 0)
+ b.append(code).append(": ");
+ b.append(message);
+ if (detailedMessage != null)
+ b.append(": ").append(detailedMessage);
+ if (cause != null)
+ append(cause, b);
+ return b.toString();
+ }
+
+ private void append(Throwable t, StringBuilder b) {
+ String lastMessage = null;
+ String message;
+ for (; t != null; t = t.getCause(), lastMessage = message) {
+ message = getMessage(t);
+ if (message == null) continue;
+ if (lastMessage != null && lastMessage.equals(message)) continue;
+ if (b.length() > 0)
+ b.append(": ");
+ b.append(message);
+ }
+ }
+
+ /**
+ * Returns a useful message from *this* exception, or null if none
+ */
+ private static String getMessage(Throwable t) {
+ String message = t.getMessage();
+ if (t.getCause() == null) {
+ if (message == null) return t.getClass().getSimpleName();
+ } else {
+ if (message == null) return null;
+ if (message.equals(t.getCause().getClass().getName() + ": " + t.getCause().getMessage())) return null;
+ }
+ return message;
+ }
+
+ @Override
+ public int hashCode() {
+ return code * 7 + message.hashCode() + (detailedMessage == null ? 0 : 17 * detailedMessage.hashCode());
+ }
+
+ /**
+ * Two error messages are equal if they have the same code and message.
+ * The cause is ignored in the comparison.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof ErrorMessage)) return false;
+
+ ErrorMessage other = (ErrorMessage) o;
+
+ if (this.code != other.code) return false;
+
+ if (!this.message.equals(other.message)) return false;
+
+ if (this.detailedMessage == null) return other.detailedMessage == null;
+ if (other.detailedMessage == null) return false;
+
+ return this.detailedMessage.equals(other.detailedMessage);
+ }
+
+ @Override
+ public ErrorMessage clone() {
+ try {
+ return (ErrorMessage) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException("Programming error");
+ }
+ }
+
+}