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

org.mockserver.exception.ExceptionHandler Maven / Gradle / Ivy

There is a newer version: 5.15.0
Show newest version
package org.mockserver.exception;

import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.ssl.NotSslRecordException;
import io.netty.util.internal.PlatformDependent;

import javax.net.ssl.SSLException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SocketChannel;
import java.util.regex.Pattern;

public class ExceptionHandler {

    private static final Pattern IGNORABLE_CLASS_IN_STACK = Pattern.compile(
        "^.*(?:Socket|Datagram|Sctp|Udt)Channel.*$");
    private static final Pattern IGNORABLE_ERROR_MESSAGE = Pattern.compile(
        "^.*(?:connection.*(?:reset|closed|abort|broken)|broken.*pipe).*$", Pattern.CASE_INSENSITIVE);

    /**
     * Closes the specified channel after all queued write requests are flushed.
     */
    public static void closeOnFlush(Channel ch) {
        if (ch != null && ch.isActive()) {
            ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    }

    /**
     * returns true is the exception was caused by the connection being closed
     */
    public static boolean shouldNotIgnoreException(Throwable cause) {
        String message = String.valueOf(cause.getMessage()).toLowerCase();

        // is ssl exception
        if (cause.getCause() instanceof SSLException || cause instanceof DecoderException | cause instanceof NotSslRecordException) {
            return false;
        }

        // first try to match connection reset / broke peer based on the regex.
        // This is the fastest way but may fail on different jdk impls or OS's
        if (IGNORABLE_ERROR_MESSAGE.matcher(message).matches()) {
            return false;
        }

        // Inspect the StackTraceElements to see if it was a connection reset / broken pipe or not
        StackTraceElement[] elements = cause.getStackTrace();
        for (StackTraceElement element : elements) {
            String classname = element.getClassName();
            String methodname = element.getMethodName();

            // skip all classes that belong to the io.netty package
            if (classname.startsWith("io.netty.")) {
                continue;
            }

            // check if the method name is read if not skip it
            if (!"read".equals(methodname)) {
                continue;
            }

            // This will also match against SocketInputStream which is used by openjdk 7 and maybe
            // also others
            if (IGNORABLE_CLASS_IN_STACK.matcher(classname).matches()) {
                return false;
            }

            try {
                // No match by now.. Try to load the class via classloader and inspect it.
                // This is mainly done as other JDK implementations may differ in name of
                // the impl.
                Class clazz = PlatformDependent.getClassLoader(ExceptionHandler.class).loadClass(classname);

                if (SocketChannel.class.isAssignableFrom(clazz)
                    || DatagramChannel.class.isAssignableFrom(clazz)) {
                    return false;
                }

                // also match against SctpChannel via String matching as it may not present.
                if (PlatformDependent.javaVersion() >= 7
                    && "com.sun.nio.sctp.SctpChannel".equals(clazz.getSuperclass().getName())) {
                    return false;
                }
            } catch (ClassNotFoundException e) {
                // This should not happen just ignore
            }
        }
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy