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

com.github.smartbuf.converter.codec.ThrowableCodec Maven / Gradle / Ivy

Go to download

SmartBuf, is a cross-language serialization and deserialization framework, and it has high performance and compression ratio like protobuf, high compatibility and scalability like json.

There is a newer version: 0.1.4
Show newest version
package com.github.smartbuf.converter.codec;

import com.github.smartbuf.converter.Codec;
import com.github.smartbuf.converter.Converter;
import com.github.smartbuf.reflect.XType;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * Codec for Throwable, support standard Throwable and StackTraceElement
 *
 * @author sulin
 * @since 2019-05-13 20:43:35
 */
@Slf4j
public final class ThrowableCodec extends Codec {

    private static final String F_DECLARER = "declarer";
    private static final String F_METHOD   = "method";
    private static final String F_FILE     = "file";
    private static final String F_LINE     = "line";

    public static final String E_TYPE   = "type";
    public static final String E_MSG    = "msg";
    public static final String E_CAUSE  = "cause";
    public static final String E_STACKS = "stacks";

    @Converter
    public StackTraceElement toStackTraceElement(Map map) {
        String declarer = convert(map.get(F_DECLARER), String.class);
        String method = convert(map.get(F_METHOD), String.class);
        String file = convert(map.get(F_FILE), String.class);
        Integer line = convert(map.get(F_LINE), Integer.class);
        if (line == null) {
            line = -1;
        }
        return new StackTraceElement(declarer, method, file, line);
    }

    @Converter
    public Map toMap(StackTraceElement element) {
        Map result = new HashMap<>();
        result.put(F_DECLARER, element.getClassName());
        result.put(F_METHOD, element.getMethodName());
        result.put(F_FILE, element.getFileName());
        result.put(F_LINE, element.getLineNumber());
        return result;
    }

    @Converter
    public Map toMap(Throwable t) {
        Map result = new HashMap<>();
        result.put(E_TYPE, t.getClass().getName());
        result.put(E_MSG, t.getMessage());
        result.put(E_CAUSE, t.getCause());
        result.put(E_STACKS, t.getStackTrace());
        return result;
    }

    @Converter
    public Throwable toThrowable(Map map, XType type) {
        String eType = convert(map.get(E_TYPE), String.class);
        // Decide class
        Class clz = type.getRawType();
        if (clz == Throwable.class && eType != null) {
            try {
                Class eClz = Class.forName(eType);
                if (Throwable.class.isAssignableFrom(eClz)) {
                    clz = eClz;
                } else {
                    log.debug("Find invalid etype[{}], as Throwable as default", eType);
                }
            } catch (ClassNotFoundException ignored) {
                log.debug("Can't find class: {}, use Throwable as default", eType);
            }
        }
        // Create Throwable
        String eMsg = convert(map.get(E_MSG), String.class);
        Throwable cause = convert(map.get(E_CAUSE), Throwable.class);
        Throwable result = createThrowable(clz, eMsg, cause);
        if (map.containsKey(E_STACKS)) {
            result.setStackTrace(convert(map.get(E_STACKS), StackTraceElement[].class));
        }
        return result;
    }

    /**
     * Create Throwable by the specified Class and parameters
     *
     * @param clz   Throwable class
     * @param msg   message parameter
     * @param cause cause parameter
     * @return Throwable
     */
    public static Throwable createThrowable(Class clz, String msg, Throwable cause) {
        if (!Throwable.class.isAssignableFrom(clz)) {
            throw new IllegalArgumentException("invalid Throwable type: " + clz);
        }
        // try Throwable(msg, cause)
        Throwable result = null;
        try {
            result = (Throwable) clz.getConstructor(String.class, Throwable.class).newInstance(msg, cause);
        } catch (Exception ignored) {
        }
        // try Throwable(msg)
        if (result == null) {
            try {
                result = (Throwable) clz.getConstructor(String.class).newInstance(msg);
            } catch (Exception ignored) {
            }
        }
        // try Throwable(cause)
        if (result == null) {
            try {
                result = (Throwable) clz.getConstructor(Throwable.class).newInstance(cause);
            } catch (Exception ignored) {
            }
        }
        // try Throwable()
        if (result == null) {
            try {
                result = (Throwable) clz.getConstructor().newInstance();
            } catch (Exception ignored) {
            }
        }
        if (result == null) {
            throw new UnsupportedOperationException("Can't initialize Throwable: " + clz);
        }
        return result;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy