org.apache.tajo.exception.ExceptionUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.tajo.exception.ExceptionUtil.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * 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 org.apache.tajo.exception;

import com.google.common.collect.Maps;
import org.apache.commons.logging.Log;
import org.apache.hadoop.util.StringUtils;
import org.apache.tajo.TajoConstants;
import org.apache.tajo.error.Errors;
import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.ReturnState;

import java.lang.reflect.Constructor;
import java.util.Map;

import static org.apache.tajo.error.Errors.ResultCode.*;
import static org.apache.tajo.exception.ReturnStateUtil.isError;

public class ExceptionUtil {

    static Map<Errors.ResultCode, Class<? extends DefaultTajoException>> EXCEPTIONS = Maps.newHashMap();

    static {

        // General Errors
        ADD_EXCEPTION(INTERNAL_ERROR, TajoInternalError.class);
        ADD_EXCEPTION(FEATURE_NOT_SUPPORTED, UnsupportedException.class);
        ADD_EXCEPTION(NOT_IMPLEMENTED, NotImplementedException.class);

        // Query Management and Scheduler
        ADD_EXCEPTION(QUERY_NOT_FOUND, QueryNotFoundException.class);

        // Session
        ADD_EXCEPTION(INVALID_SESSION, InvalidSessionException.class);
        ADD_EXCEPTION(NO_SUCH_SESSION_VARIABLE, NoSuchSessionVariableException.class);
        ADD_EXCEPTION(INVALID_SESSION_VARIABLE, InvalidSessionVariableException.class);

        // Data Exception (SQLState Class - 22)
        ADD_EXCEPTION(DIVISION_BY_ZERO, DividedByZeroException.class);
        ADD_EXCEPTION(INVALID_URL, InvalidURLException.class);
        ADD_EXCEPTION(INVALID_VALUE_FOR_CAST, InvalidValueForCastException.class);

        // Syntax Error or Access Rule Violation
        ADD_EXCEPTION(SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION, SQLSyntaxError.class);
        ADD_EXCEPTION(SYNTAX_ERROR, SQLSyntaxError.class);
        ADD_EXCEPTION(INSUFFICIENT_PRIVILEGE, InsufficientPrivilegeException.class);
        ADD_EXCEPTION(CANNOT_DROP_CURRENT_DATABASE, CannotDropCurrentDatabaseException.class);

        ADD_EXCEPTION(UNDEFINED_TABLESPACE, UndefinedTablespaceException.class);
        ADD_EXCEPTION(UNDEFINED_DATABASE, UndefinedDatabaseException.class);
        // ADD_EXCEPTION(UNDEFINED_SCHEMA, );
        ADD_EXCEPTION(UNDEFINED_TABLE, UndefinedTableException.class);
        ADD_EXCEPTION(UNDEFINED_COLUMN, UndefinedColumnException.class);
        ADD_EXCEPTION(UNDEFINED_FUNCTION, UndefinedFunctionException.class);
        ADD_EXCEPTION(UNDEFINED_PARTITION_METHOD, UndefinedPartitionMethodException.class);
        ADD_EXCEPTION(UNDEFINED_PARTITION, UndefinedPartitionException.class);
        ADD_EXCEPTION(UNDEFINED_PARTITION_KEY, UndefinedPartitionKeyException.class);
        ADD_EXCEPTION(UNDEFINED_OPERATOR, UndefinedOperatorException.class);
        ADD_EXCEPTION(UNDEFINED_INDEX_NAME, UndefinedIndexException.class);
        ADD_EXCEPTION(UNDEFINED_TABLESPACE_HANDLER, UndefinedTablespaceHandlerException.class);

        ADD_EXCEPTION(DUPLICATE_TABLESPACE, DuplicateTablespaceException.class);
        ADD_EXCEPTION(DUPLICATE_DATABASE, DuplicateDatabaseException.class);
        // ADD_EXCEPTION(DUPLICATE_SCHEMA, );
        ADD_EXCEPTION(DUPLICATE_TABLE, DuplicateTableException.class);
        ADD_EXCEPTION(DUPLICATE_COLUMN, DuplicateColumnException.class);
        // ADD_EXCEPTION(DUPLICATE_ALIAS, );
        ADD_EXCEPTION(DUPLICATE_INDEX, DuplicateIndexException.class);
        ADD_EXCEPTION(DUPLICATE_PARTITION, DuplicatePartitionException.class);

        ADD_EXCEPTION(AMBIGUOUS_TABLE, AmbiguousTableException.class);
        ADD_EXCEPTION(AMBIGUOUS_COLUMN, AmbiguousColumnException.class);
        ADD_EXCEPTION(AMBIGUOUS_FUNCTION, AmbiguousFunctionException.class);

        // Expressions
        ADD_EXCEPTION(DATATYPE_MISMATCH, DataTypeMismatchException.class);

        ADD_EXCEPTION(UNAVAILABLE_TABLE_LOCATION, UnavailableTableLocationException.class);
        ADD_EXCEPTION(UNKNOWN_DATAFORMAT, UnknownDataFormatException.class);
        ADD_EXCEPTION(UNSUPPORTED_DATATYPE, UnsupportedDataTypeException.class);
        ADD_EXCEPTION(INVALID_DATATYPE, InvalidDataTypeException.class);
        ADD_EXCEPTION(INVALID_TABLE_PROPERTY, InvalidTablePropertyException.class);
        ADD_EXCEPTION(MISSING_TABLE_PROPERTY, MissingTablePropertyException.class);

        ADD_EXCEPTION(TOO_LARGE_INPUT_FOR_CROSS_JOIN, TooLargeInputForCrossJoinException.class);
        ADD_EXCEPTION(INVALID_INPUTS_FOR_CROSS_JOIN, InvalidInputsForCrossJoin.class);

        ADD_EXCEPTION(CAT_UNSUPPORTED_CATALOG_STORE, UnsupportedCatalogStore.class);
    }

    private static void ADD_EXCEPTION(Errors.ResultCode code, Class<? extends DefaultTajoException> cls) {
        EXCEPTIONS.put(code, cls);
    }

    /**
     * If the exception is equivalent to the error corresponding to the expected exception, throws the exception.
     * It is used to throw an exception for a error.
     *
     * @param state ReturnState
     * @param clazz Exception class corresponding to the expected
     * @param <T> Exception class
     * @throws T Exception
     */
    public static <T extends TajoException> void throwsIfThisError(ReturnState state, Class<T> clazz) throws T {
        if (isError(state)) {
            T exception = (T) toTajoException(state);
            if (exception.getClass().equals(clazz)) {
                throw exception;
            }
        }
    }

    /**
     * It can throw any TajoException if any error occurs.
     *
     * @param state
     * @throws TajoException
     */
    public static void throwIfError(ReturnState state) throws TajoException {
        if (isError(state)) {
            throw toTajoException(state);
        }
    }

    public static DefaultTajoException toTajoExceptionCommon(ReturnState state) {
        if (state.getReturnCode() == Errors.ResultCode.INTERNAL_ERROR) {
            return new TajoInternalError(state);

        } else if (EXCEPTIONS.containsKey(state.getReturnCode())) {
            Object exception;
            try {
                Class clazz = EXCEPTIONS.get(state.getReturnCode());
                Constructor c = clazz.getConstructor(ReturnState.class);
                exception = c.newInstance(new Object[] { state });
            } catch (Throwable t) {
                throw new TajoInternalError(t);
            }

            if (exception instanceof TajoException) {
                return (TajoException) exception;
            } else if (exception instanceof TajoRuntimeException) {
                return ((TajoRuntimeException) exception);
            } else {
                return ((TajoError) exception);
            }

        } else {
            throw new TajoInternalError("Cannot restore the exception for [" + state.getReturnCode().name() + "] '"
                    + state.getMessage() + "'");
        }
    }

    public static TajoException toTajoException(ReturnState state) throws TajoRuntimeException, TajoError {
        DefaultTajoException e = toTajoExceptionCommon(state);

        if (e instanceof TajoException) {
            return (TajoException) e;
        } else if (e instanceof TajoRuntimeException) {
            throw ((TajoRuntimeException) e);
        } else {
            throw ((TajoError) e);
        }
    }

    /**
     * Determine if a Throwable has Tajo's ReturnCode and error message.
     *
     * @param t Throwable
     * @return true if a Throwable has Tajo's ReturnCode and error message.
     */
    public static boolean isExceptionWithResultCode(Throwable t) {
        return t instanceof DefaultTajoException;
    }

    /**
     * Determine if a Throwable is caused by user's wrong input and invalid data instead of a bug.
     *
     * @param t Throwable
     * @return true if a Throwable has Tajo's ReturnCode and error message.
     */
    public static boolean isManagedException(Throwable t) {
        return t instanceof TajoException || t instanceof TajoRuntimeException;
    }

    private static void printStackTrace(Log log, Throwable t) {
        log.error("\nStack Trace:\n" + StringUtils.stringifyException(t));
    }

    public static void printStackTraceIfError(Log log, Throwable t) {
        // if this runs as an actual cluster instance or a debug mode, it will print all stacktraces.
        // In other cases (i.e., run as a test mode and not debug mode), it will print stacktraces
        // if the query is managed mode.
        if (!TajoConstants.IS_TEST_MODE || TajoConstants.IS_DEBUG_MODE || !ExceptionUtil.isManagedException(t)) {
            ExceptionUtil.printStackTrace(log, t);
        }
    }

    public static UnsupportedException makeNotSupported(String feature) {
        return new UnsupportedException(feature);
    }

    /**
     * Return the string about the exception line ; e.g.,)
     * <code>Line 195 in JdbcTablespace.java</code>
     *
     * @return A string representing the line number and source file name at which the exception occurs.
     */
    @SuppressWarnings("unused")
    public static String getExceptionLine() {
        StackTraceElement stack = Thread.currentThread().getStackTrace()[3];
        return "Line " + stack.getLineNumber() + " in " + stack.getFileName();
    }

    /**
     * Return the string about the exception point; e.g.,)
     * <code>org.apache.tajo.storage.mysql.JdbcTablespace::createTable</code>
     *
     * @return A string representing the class and method names at which the exception occurs.
     */
    public static String getExceptionPoint() {
        StackTraceElement stack = Thread.currentThread().getStackTrace()[3];
        return stack.getClassName() + "::" + stack.getMethodName();
    }
}