com.basho.riak.client.raw.JSONErrorParser.java Source code

Java tutorial

Introduction

Here is the source code for com.basho.riak.client.raw.JSONErrorParser.java

Source

/*
 * This file is provided 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 com.basho.riak.client.raw;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.basho.riak.client.RiakException;
import com.basho.riak.client.raw.query.MapReduceTimeoutException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

/**
 * Exceptions come back from Riak as JSON, parses exceptions, and throws the
 * most specific exception it can.
 * 
 * @author russell
 * 
 */
public class JSONErrorParser {
    private static final String PBSOCKET_PRE_1_1_TIMEOUT_TUPLE = "{error,timeout}";
    private static final String PARSE_ERROR = ". Additionally, an error was thrown parsing the error response.";
    private static final String ERROR_KEY = "error";
    private static final String TIMEOUT_VALUE = "timeout";
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * Parses some Riak error <code>json</code> into a checked exception of the
     * most specific type it can manage.
     * 
     * @param json
     *            The error from Riak
     * @return a {@link RiakException} as specific as possible
     * @throws IOException
     */
    public static RiakException parseException(final String json) {
        RiakException ex = null;
        try {
            Map<String, String> exceptionData = parseError(json);

            if (isTimeoutError(exceptionData)) {
                ex = new MapReduceTimeoutException();
            } else {
                ex = new RiakException(json);
            }
        } catch (IOException e) {
            ex = new RiakException(new StringBuilder().append(json).append(PARSE_ERROR).toString(), e);
        }

        return ex;
    }

    /**
     * Does the <code>json</code> represent a riak map/reduce timeout exception?
     * 
     * @param json
     *            an error String from Riak
     * @return true if <code>json</code> represents an m/r timeout, false
     *         otherwse
     * @throws IOException
     */
    public static boolean isTimeoutException(final String json) {

        try {
            Map<String, String> exceptionData = parseError(json);
            return isTimeoutError(exceptionData);
        } catch (IOException e) {
            // what about an old skool Erlang term exception from the PB Socket?
            // fall back to the string match on 'timeout'
            // TODO: @remove:1.2
            if (PBSOCKET_PRE_1_1_TIMEOUT_TUPLE.equals(json)) {
                return true;
            }
            // can't be a timeout if we can't parse it
            return false;
        }
    }

    /**
     * Internal parse method, just calls ObjectMapper to get a map from the
     * string
     * 
     * @param json
     *            a JSON String
     * @return the Map representation of the JSON
     * @throws IOException
     */
    private static final Map<String, String> parseError(final String json) throws IOException {
        return objectMapper.readValue(json,
                objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, String.class));
    }

    /**
     * Does the map of exception data represent an m/r timeout exception?
     * 
     * @param exceptionData
     * @return true if <code>exceptionData</code> contains key "error" with
     *         value "timeout". False otherwise.
     */
    private static boolean isTimeoutError(final Map<String, String> exceptionData) {
        return (exceptionData.containsKey(ERROR_KEY) && TIMEOUT_VALUE.equals(exceptionData.get(ERROR_KEY)));
    }

}