blob: 6b6de600f0df8b0a8f7fb5cd53dbe6831b8a9e9c [file] [log] [blame]
package com.google.net.stubby;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.net.stubby.transport.Transport;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* Defines the status of an operation using the canonical error space.
*/
@Immutable
public class Status {
public static final Status OK = new Status(Transport.Code.OK);
public static final Status CANCELLED = new Status(Transport.Code.CANCELLED);
public static Status fromThrowable(Throwable t) {
for (Throwable cause : Throwables.getCausalChain(t)) {
if (cause instanceof OperationException) {
return ((Status.OperationException) cause).getStatus();
} else if (cause instanceof OperationRuntimeException) {
return ((Status.OperationRuntimeException) cause).getStatus();
}
}
// Couldn't find a cause with a Status
return new Status(Transport.Code.INTERNAL, t);
}
private final Transport.Code code;
private final String description;
private final Throwable cause;
public Status(Transport.Code code) {
this(code, null, null);
}
public Status(Transport.Code code, @Nullable String description) {
this(code, description, null);
}
public Status(Transport.Code code, @Nullable Throwable cause) {
this(code, null, cause);
}
public Status(Transport.Code code, @Nullable String description, @Nullable Throwable cause) {
this.code = Preconditions.checkNotNull(code);
this.description = description;
this.cause = cause;
}
public Transport.Code getCode() {
return code;
}
@Nullable
public String getDescription() {
return description;
}
@Nullable
public Throwable getCause() {
return cause;
}
public boolean isOk() {
return OK.getCode() == getCode();
}
/**
* Override this status with another if allowed.
*/
public Status overrideWith(Status newStatus) {
if (this.getCode() == Transport.Code.OK || newStatus.code == Transport.Code.OK) {
return this;
} else {
return newStatus;
}
}
public RuntimeException asRuntimeException() {
return new OperationRuntimeException(this);
}
public Exception asException() {
return new OperationException(this);
}
/**
* Exception thrown by implementations while managing an operation.
*/
public static class OperationException extends Exception {
private final Status status;
public OperationException(Status status) {
super(status.getCode() + ": " + status.getDescription(), status.getCause());
this.status = status;
}
public Status getStatus() {
return status;
}
}
/**
* Runtime exception thrown by implementations while managing an operation.
*/
public static class OperationRuntimeException extends RuntimeException {
private final Status status;
public OperationRuntimeException(Status status) {
super(status.getCode() + ": " + status.getDescription(), status.getCause());
this.status = status;
}
public Status getStatus() {
return status;
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[").append(code);
if (description != null) {
builder.append(";").append(description);
}
if (cause != null) {
builder.append(";").append(cause);
}
builder.append("]");
return builder.toString();
}
}