All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.jsonrpc4j.DefaultExceptionResolver Maven / Gradle / Ivy

Go to download

This project aims to provide the facility to easily implement JSON-RPC for the java programming language.

There is a newer version: 1.6
Show newest version
package com.googlecode.jsonrpc4j;

import static com.googlecode.jsonrpc4j.Util.hasNonNullObjectData;
import static com.googlecode.jsonrpc4j.Util.hasNonNullTextualData;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.node.ObjectNode;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Default implementation of the {@link ExceptionResolver} interface that attempts to re-throw the same exception
 * that was thrown by the server.  This always returns a {@link Throwable}.
 */
@SuppressWarnings("WeakerAccess")
public enum DefaultExceptionResolver implements ExceptionResolver {
	INSTANCE;
	private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionResolver.class);

	/**
	 * {@inheritDoc}
	 */
	public Throwable resolveException(ObjectNode response) {
		ObjectNode errorObject = ObjectNode.class.cast(response.get(JsonRpcBasicServer.ERROR));
		if (!hasNonNullObjectData(errorObject, JsonRpcBasicServer.DATA)) return createJsonRpcClientException(errorObject);

		ObjectNode dataObject = ObjectNode.class.cast(errorObject.get(JsonRpcBasicServer.DATA));
		if (!hasNonNullTextualData(dataObject, JsonRpcBasicServer.EXCEPTION_TYPE_NAME)) return createJsonRpcClientException(errorObject);

		try {
			String exceptionTypeName = dataObject.get(JsonRpcBasicServer.EXCEPTION_TYPE_NAME).asText();
			String message = hasNonNullTextualData(dataObject, JsonRpcBasicServer.ERROR_MESSAGE) ? dataObject.get(JsonRpcBasicServer.ERROR_MESSAGE).asText() : null;
			return createThrowable(exceptionTypeName, message);
		} catch (Exception e) {
			logger.warn("Unable to create throwable", e);
			return createJsonRpcClientException(errorObject);
		}
	}

	/**
	 * Creates a {@link JsonRpcClientException} from the given
	 * {@link ObjectNode}.
	 *
	 * @param errorObject the error object
	 * @return the exception
	 */
	private JsonRpcClientException createJsonRpcClientException(ObjectNode errorObject) {
		int code = errorObject.has(JsonRpcBasicServer.ERROR_CODE) ? errorObject.get(JsonRpcBasicServer.ERROR_CODE).asInt() : 0;
		return new JsonRpcClientException(code, errorObject.get(JsonRpcBasicServer.ERROR_MESSAGE).asText(), errorObject.get(JsonRpcBasicServer.DATA));
	}

	/**
	 * Attempts to create an {@link Throwable} of the given type  with the given message.  For this method to create a
	 * {@link Throwable} it must have either a default (no-args) constructor or a  constructor that takes a {@code String}
	 * as the message name.  null is returned if a {@link Throwable} can't be created.
	 *
	 * @param typeName the java type name (class name)
	 * @param message  the message
	 * @return the throwable
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws IllegalArgumentException
	 */
	private Throwable createThrowable(String typeName, String message) throws IllegalAccessException, InvocationTargetException, InstantiationException {
		Class clazz = loadThrowableClass(typeName);
		if (clazz == null) return null;

		Constructor defaultCtr = getDefaultConstructor(clazz);
		Constructor messageCtr = getMessageConstructor(clazz);

		if (message != null && messageCtr != null) {
			return messageCtr.newInstance(message);
		} else if (message != null && defaultCtr != null) {
			logger.warn("Unable to invoke message constructor for {}, fallback to default", clazz.getName());
			return defaultCtr.newInstance();
		} else if (message == null && defaultCtr != null) {
			return defaultCtr.newInstance();
		} else if (message == null && messageCtr != null) {
			logger.warn("Passing null message to message constructor for {}", clazz.getName());
			return messageCtr.newInstance((String) null);
		} else {
			logger.error("Unable to find message or default constructor for {} have {}", clazz.getName(), clazz.getDeclaredConstructors());
			return null;
		}
	}

	private Class loadThrowableClass(String typeName) {
		Class clazz;
		try {
			clazz = Class.forName(typeName);
			if (!Throwable.class.isAssignableFrom(clazz)) {
				logger.warn("Type does not inherit from Throwable {}", clazz.getName());
			} else {
				return clazz.asSubclass(Throwable.class);
			}
		} catch (Exception e) {
			logger.warn("Unable to load Throwable class {}", typeName);
		}
		return null;
	}

	private Constructor getDefaultConstructor(Class clazz) {
		Constructor defaultCtr = null;
		try {
			defaultCtr = clazz.getConstructor();
		} catch (NoSuchMethodException e) {
			handleException(e);
		}
		return defaultCtr;
	}

	private Constructor getMessageConstructor(Class clazz) {
		Constructor messageCtr = null;
		try {
			messageCtr = clazz.getConstructor(String.class);
		} catch (NoSuchMethodException e) {
			handleException(e);
		}
		return messageCtr;
	}

	@SuppressWarnings("UnusedParameters")
	private void handleException(Exception e) {
		/* do nothing */
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy