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

com.dimajix.flowman.grpc.ExceptionUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2023 The Flowman Authors
 *
 * 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.dimajix.flowman.grpc;

import java.util.Arrays;
import java.util.stream.Collectors;

import com.dimajix.shaded.grpc.Metadata;
import com.dimajix.shaded.grpc.Status;
import com.dimajix.shaded.grpc.StatusException;
import com.dimajix.shaded.grpc.StatusRuntimeException;
import com.dimajix.shaded.grpc.protobuf.ProtoUtils;
import lombok.val;

import com.dimajix.flowman.kernel.proto.Exception;
import com.dimajix.flowman.kernel.proto.StackTraceElement;


public class ExceptionUtils {
    static private StackTraceElement wrap(java.lang.StackTraceElement se) {
        val builder = StackTraceElement.newBuilder();
        //if (se.getClassLoaderName() != null)
        //    builder.setClassLoaderName(se.getClassLoaderName());
        //if (se.getModuleName() != null)
        //    builder.setModuleName(se.getModuleName());
        //if (se.getModuleVersion() != null)
        //    builder.setModuleVersion(se.getModuleVersion());
        builder.setDeclaringClass(se.getClassName());
        builder.setMethodName(se.getMethodName());
        if (se.getFileName() != null)
            builder.setFileName(se.getFileName());
        builder.setLineNumber(se.getLineNumber());
        return builder.build();
    }

    static private java.lang.StackTraceElement unwrap(StackTraceElement se) {
        return new java.lang.StackTraceElement(
            //se.hasClassLoaderName() ? se.getClassLoaderName() : null,
            //se.hasModuleName() ? se.getModuleName() : null,
            //se.hasModuleVersion() ? se.getModuleVersion() : null,
            se.getDeclaringClass(),
            se.getMethodName(),
            se.hasFileName() ? se.getFileName() : null,
            se.getLineNumber()
        );
    }

    static public Exception wrap(Throwable t, boolean withStacktrace) {
        val builder = Exception.newBuilder()
            .setClassName(t.getClass().getSimpleName())
            .setFqName(t.getClass().getCanonicalName());
        // We disable stacktraces, because errors would be too big for the transport protocol
        if (withStacktrace && t.getStackTrace() != null && t.getStackTrace().length > 0) {
            val stacktrace = Arrays.stream(t.getStackTrace())
                .limit(16)
                .map(ExceptionUtils::wrap)
                .collect(Collectors.toList());
            builder.addAllStackTrace(stacktrace);
        }
        if (t.getMessage() != null) {
            builder.setMessage(t.getMessage());
        }
        if (t.getCause() != null && t.getCause() != t) {
            builder.setCause(wrap(t.getCause(), withStacktrace));
        }
        if (t.getSuppressed() != null && t.getSuppressed().length > 0) {
            builder.addAllSuppressed(Arrays.stream(t.getSuppressed()).map(e -> wrap(e, withStacktrace)).collect(Collectors.toList()));
        }

        return builder.build();
    }

    static public RemoteException unwrap(Exception ex) {
        val cause = ex.hasCause() ? unwrap(ex.getCause()) : null;
        RemoteException result = new RemoteException(ex.getFqName(), ex.hasMessage() ? ex.getMessage() : null, cause);

        // The stacktrace can only be set for exceptions which are thrown
        if (ex.getStackTraceCount() > 0) {
            try {
                throw result;
            } catch (RemoteException ex2) {
                result = ex2;
            }
            val st = ex.getStackTraceList().stream().map(ExceptionUtils::unwrap).toArray(java.lang.StackTraceElement[]::new);
            result.setStackTrace(st);
        }

        if (ex.getSuppressedCount() > 0) {
            ex.getSuppressedList().stream().map(ExceptionUtils::unwrap).forEach(result::addSuppressed);
        }
        return result;
    }

    static public StatusException asStatusException(Status status, Throwable t, boolean withStacktrace) {
        val trailers = new Metadata();
        trailers.put(ProtoUtils.keyForProto(Exception.getDefaultInstance()), ExceptionUtils.wrap(t, withStacktrace));

        return status
            .withCause(t)
            .withDescription(t.getMessage())
            .asException(trailers);
    }

    static public RuntimeException asRemoteException(StatusRuntimeException ex) {
        val trailers = ex.getTrailers();
        if (trailers == null) {
            return ex;
        }

        val exception = trailers.get(ProtoUtils.keyForProto(Exception.getDefaultInstance()));
        if (exception == null) {
            return ex;
        }

        return unwrap(exception);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy