/* * Copyright (c) 2016 Couchbase, Inc. * * Licensed 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 com.couchbase.client.core.endpoint; import com.couchbase.client.core.endpoint.kv.ErrorMap; import com.couchbase.client.core.endpoint.kv.KeyValueStatus; import com.couchbase.client.core.logging.CouchbaseLogger; import com.couchbase.client.core.logging.CouchbaseLoggerFactory; import com.couchbase.client.core.message.ResponseStatus; /** * Helper class to easily convert different handler status types to a common one. * * @author Michael Nitschinger * @since 1.1.2 * @see ResponseStatus * @see KeyValueStatus */ public class ResponseStatusConverter { /** * Start with a static empty kv error map. */ private static volatile ErrorMap BINARY_ERROR_MAP = null; /** * The logger used. */ private static final CouchbaseLogger LOGGER = CouchbaseLoggerFactory.getInstance(ResponseStatusConverter.class); public static final int HTTP_OK = 200; public static final int HTTP_CREATED = 201; public static final int HTTP_ACCEPTED = 202; public static final int HTTP_BAD_REQUEST = 400; public static final int HTTP_NOT_FOUND = 404; public static final int HTTP_INTERNAL_ERROR = 500; /** * Convert the binary protocol status in a typesafe enum that can be acted upon later. * * @param code the status to convert. * @return the converted response status. */ public static ResponseStatus fromBinary(final short code) { KeyValueStatus status = KeyValueStatus.valueOf(code); switch (status) { case SUCCESS: return ResponseStatus.SUCCESS; case ERR_EXISTS: return ResponseStatus.EXISTS; case ERR_NOT_FOUND: return ResponseStatus.NOT_EXISTS; case ERR_NOT_MY_VBUCKET: return ResponseStatus.RETRY; case ERR_NOT_STORED: return ResponseStatus.NOT_STORED; case ERR_TOO_BIG: return ResponseStatus.TOO_BIG; case ERR_TEMP_FAIL: return ResponseStatus.TEMPORARY_FAILURE; case ERR_BUSY: return ResponseStatus.SERVER_BUSY; case ERR_NO_MEM: return ResponseStatus.OUT_OF_MEMORY; case ERR_UNKNOWN_COMMAND: return ResponseStatus.COMMAND_UNAVAILABLE; case ERR_NOT_SUPPORTED: return ResponseStatus.COMMAND_UNAVAILABLE; case ERR_ACCESS: return ResponseStatus.ACCESS_ERROR; case ERR_INTERNAL: return ResponseStatus.INTERNAL_ERROR; case ERR_INVALID: return ResponseStatus.INVALID_ARGUMENTS; case ERR_DELTA_BADVAL: return ResponseStatus.INVALID_ARGUMENTS; case ERR_RANGE: return ResponseStatus.RANGE_ERROR; case ERR_ROLLBACK: return ResponseStatus.ROLLBACK; //== the following codes are for subdocument API == case ERR_SUBDOC_PATH_NOT_FOUND: return ResponseStatus.SUBDOC_PATH_NOT_FOUND; case ERR_SUBDOC_PATH_MISMATCH: return ResponseStatus.SUBDOC_PATH_MISMATCH; case ERR_SUBDOC_PATH_INVALID: return ResponseStatus.SUBDOC_PATH_INVALID; case ERR_SUBDOC_PATH_TOO_BIG: return ResponseStatus.SUBDOC_PATH_TOO_BIG; case ERR_SUBDOC_DOC_TOO_DEEP: return ResponseStatus.SUBDOC_DOC_TOO_DEEP; case ERR_SUBDOC_VALUE_CANTINSERT: return ResponseStatus.SUBDOC_VALUE_CANTINSERT; case ERR_SUBDOC_DOC_NOT_JSON: return ResponseStatus.SUBDOC_DOC_NOT_JSON; case ERR_SUBDOC_NUM_RANGE: return ResponseStatus.SUBDOC_NUM_RANGE; case ERR_SUBDOC_DELTA_RANGE: return ResponseStatus.SUBDOC_DELTA_RANGE; case ERR_SUBDOC_PATH_EXISTS: return ResponseStatus.SUBDOC_PATH_EXISTS; case ERR_SUBDOC_VALUE_TOO_DEEP: return ResponseStatus.SUBDOC_VALUE_TOO_DEEP; case ERR_SUBDOC_INVALID_COMBO: return ResponseStatus.SUBDOC_INVALID_COMBO; case ERR_SUBDOC_MULTI_PATH_FAILURE: return ResponseStatus.SUBDOC_MULTI_PATH_FAILURE; case ERR_SUBDOC_XATTR_INVALID_FLAG_COMBO: return ResponseStatus.INTERNAL_ERROR; case ERR_SUBDOC_XATTR_UNKNOWN_MACRO: return ResponseStatus.SUBDOC_XATTR_UNKNOWN_MACRO; case ERR_SUBDOC_XATTR_INVALID_KEY_COMBO: return ResponseStatus.SUBDOC_XATTR_INVALID_KEY_COMBO; //== end of subdocument API codes == default: if (BINARY_ERROR_MAP == null) { LOGGER.warn("Unexpected ResponseStatus with Protocol KeyValue: {} (0x{}, {})", status, Integer.toHexString(status.code()), status.description()); return ResponseStatus.FAILURE; } else { ErrorMap.ErrorCode result = BINARY_ERROR_MAP.errors().get(status.code()); if (result == null) { LOGGER.warn("Unexpected ResponseStatus with Protocol KeyValue and not found in " + "Error Map: {} (0x{}, {})", status, Integer.toHexString(status.code()), status.description()); } else { LOGGER.warn("Unexpected ResponseStatus with Extended Error {}", result.toString()); } return ResponseStatus.FAILURE; } } } /** * Convert the http protocol status in a typesafe enum that can be acted upon later. * * @param code the status to convert. * @return the converted response status. */ public static ResponseStatus fromHttp(final int code) { ResponseStatus status; switch (code) { case HTTP_OK: case HTTP_CREATED: case HTTP_ACCEPTED: status = ResponseStatus.SUCCESS; break; case HTTP_NOT_FOUND: status = ResponseStatus.NOT_EXISTS; break; case HTTP_BAD_REQUEST: status = ResponseStatus.INVALID_ARGUMENTS; break; case HTTP_INTERNAL_ERROR: status = ResponseStatus.INTERNAL_ERROR; break; default: LOGGER.warn("Unknown ResponseStatus with Protocol HTTP: {}", code); status = ResponseStatus.FAILURE; } return status; } /** * Updates the current error map in use for all uses of the response status converter. * * If the provided one is older than the one stored, this update operation will be ignored. * * @param map the map in use, it always uses the latest one. */ public static void updateBinaryErrorMap(final ErrorMap map) { if (map == null) { return; } if (BINARY_ERROR_MAP == null || map.compareTo(BINARY_ERROR_MAP) > 0) { BINARY_ERROR_MAP = map; } } /** * Get the current error map used by the response status converter * * @return error map */ public static ErrorMap getBinaryErrorMap() { return BINARY_ERROR_MAP; } }