blob: 846e2930e8880a17ea527650af266afca74465f1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.rest;
import java.util.Collection;
import java.util.Collections;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.language.Translatable;
import org.apache.guacamole.language.TranslatableMessage;
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
import org.apache.guacamole.tunnel.GuacamoleStreamException;
/**
* Describes an error that occurred within a REST endpoint.
*/
public class APIError {
/**
* The translation key of the generic translation string which should be
* used to display arbitrary messages which otherwise have no translation
* string.
*/
private static final String UNTRANSLATED_MESSAGE_KEY = "APP.TEXT_UNTRANSLATED";
/**
* The name of the placeholder within the translation string associated with
* UNTRANSLATED_MESSAGE_KEY that should receive the raw, untranslated text.
*/
private static final String UNTRANSLATED_MESSAGE_VARIABLE_NAME = "MESSAGE";
/**
* The human-readable error message.
*/
private final String message;
/**
* A translatable message representing the error that occurred.
*/
private final TranslatableMessage translatableMessage;
/**
* The associated Guacamole protocol status code.
*/
private final Integer statusCode;
/**
* All expected request parameters, if any, as a collection of fields.
*/
private final Collection<Field> expected;
/**
* The type of error that occurred.
*/
private final Type type;
/**
* All possible types of REST API errors.
*/
public enum Type {
/**
* The requested operation could not be performed because the request
* itself was malformed.
*/
BAD_REQUEST,
/**
* The credentials provided were invalid.
*/
INVALID_CREDENTIALS,
/**
* The credentials provided were not necessarily invalid, but were not
* sufficient to determine validity.
*/
INSUFFICIENT_CREDENTIALS,
/**
* An internal server error has occurred.
*/
INTERNAL_ERROR,
/**
* An object related to the request does not exist.
*/
NOT_FOUND,
/**
* Permission was denied to perform the requested operation.
*/
PERMISSION_DENIED,
/**
* An error occurred within an intercepted stream, terminating that
* stream. The Guacamole protocol status code of that error can be
* retrieved with getStatusCode().
*/
STREAM_ERROR;
/**
* Returns the REST API error type which corresponds to the type of the
* given exception.
*
* @param exception
* The exception to use to derive the API error type.
*
* @return
* The API error type which corresponds to the type of the given
* exception.
*/
public static Type fromGuacamoleException(GuacamoleException exception) {
// Additional credentials are needed
if (exception instanceof GuacamoleInsufficientCredentialsException)
return INSUFFICIENT_CREDENTIALS;
// The provided credentials are wrong
if (exception instanceof GuacamoleInvalidCredentialsException)
return INVALID_CREDENTIALS;
// Generic permission denied
if (exception instanceof GuacamoleSecurityException)
return PERMISSION_DENIED;
// Arbitrary resource not found
if (exception instanceof GuacamoleResourceNotFoundException)
return NOT_FOUND;
// Arbitrary bad requests
if (exception instanceof GuacamoleClientException)
return BAD_REQUEST;
// Errors from intercepted streams
if (exception instanceof GuacamoleStreamException)
return STREAM_ERROR;
// All other errors
return INTERNAL_ERROR;
}
}
/**
* Creates a new APIError which exposes the details of the given
* GuacamoleException. If the given GuacamoleException implements
* Translatable, then its translation string and values will be exposed as
* well.
*
* @param exception
* The GuacamoleException from which the details of the new APIError
* should be derived.
*/
public APIError(GuacamoleException exception) {
// Build base REST service error
this.type = Type.fromGuacamoleException(exception);
this.message = exception.getMessage();
// Add expected credentials if applicable
if (exception instanceof GuacamoleCredentialsException) {
GuacamoleCredentialsException credentialsException = (GuacamoleCredentialsException) exception;
this.expected = credentialsException.getCredentialsInfo().getFields();
}
else
this.expected = null;
// Add stream status code if applicable
if (exception instanceof GuacamoleStreamException) {
GuacamoleStreamException streamException = (GuacamoleStreamException) exception;
this.statusCode = streamException.getStatus().getGuacamoleStatusCode();
}
else
this.statusCode = null;
// Pull translatable message and values if available
if (exception instanceof Translatable) {
Translatable translatable = (Translatable) exception;
this.translatableMessage = translatable.getTranslatableMessage();
}
// Use generic translation string if message is not translated
else
this.translatableMessage = new TranslatableMessage(UNTRANSLATED_MESSAGE_KEY,
Collections.singletonMap(UNTRANSLATED_MESSAGE_VARIABLE_NAME, this.message));
}
/**
* Returns the type of error that occurred.
*
* @return
* The type of error that occurred.
*/
public Type getType() {
return type;
}
/**
* Returns the Guacamole protocol status code associated with the error
* that occurred. This is only valid for errors of type STREAM_ERROR.
*
* @return
* The Guacamole protocol status code associated with the error that
* occurred. If the error is not of type STREAM_ERROR, this will be
* null.
*/
public Integer getStatusCode() {
return statusCode;
}
/**
* Returns a collection of all required parameters, where each parameter is
* represented by a field.
*
* @return
* A collection of all required parameters.
*/
public Collection<Field> getExpected() {
return expected;
}
/**
* Returns a human-readable error message describing the error that
* occurred.
*
* @return
* A human-readable error message.
*/
public String getMessage() {
return message;
}
/**
* Returns a translatable message describing the error that occurred. If no
* translatable message is associated with the error, this will be null.
*
* @return
* A translatable message describing the error that occurred, or null
* if there is no such message defined.
*/
public TranslatableMessage getTranslatableMessage() {
return translatableMessage;
}
}