/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * 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 org.pentaho.di.core.database.util; import org.pentaho.di.compatibility.ValueString; import org.pentaho.di.core.database.DatabaseInterface; import org.pentaho.di.core.database.DatabaseInterfaceExtended; import org.pentaho.di.core.exception.KettleDatabaseException; import org.pentaho.di.core.logging.LogChannelInterface; import org.pentaho.di.core.logging.LogTableCoreInterface; import org.pentaho.di.i18n.BaseMessages; public class DatabaseLogExceptionFactory { public static final String KETTLE_GLOBAL_PROP_NAME = "KETTLE_FAIL_ON_LOGGING_ERROR"; private static final LogExceptionBehaviourInterface throwable = new ThrowableBehaviour(); private static final LogExceptionBehaviourInterface suppressable = new SuppressBehaviour(); private static final LogExceptionBehaviourInterface suppressableWithShortMessage = new SuppressableWithShortMessage(); /** * <p> * Returns throw exception strategy depends on defined behavior. Default is suppress exception. * </p> * <p/> * <p> * This behavior can be overridden with 'kettle.properties' key-value using 'Edit Kettle.properties file' in Spoon or * other. * </p> * <p/> * <p> * Following this strategy - <code>System.getProperty(String key)</code> call will be used to check if key-value pair * is defined. If not found default behavior will be used. If not found and value is TRUE/Y - throwable behavior will * be used. * </p> * * @param table * logging table that participated in exception. Must be instance of {@link LogTableCoreInterface}, otherwise * default suppress exception behavior will be used. * @return * @see {@link org.pentaho.di.core.Const#KETTLE_VARIABLES_FILE} */ public static LogExceptionBehaviourInterface getExceptionStrategy( LogTableCoreInterface table ) { return getExceptionStrategy( table, null ); } /** * <p> * Returns throw exception strategy depends on defined behavior. Default is suppress exception. * </p> * <p/> * <p> * This behavior can be overridden with 'kettle.properties' key-value using 'Edit Kettle.properties file' in Spoon or * other. * </p> * <p/> * <p> * Following this strategy - <code>System.getProperty(String key)</code> call will be used to check if key-value pair * is defined. If key-value pair is not defined or value is set to FALSE/N, exception will be checked and suppressable strategy * with short message can be chosen, otherwise throwable behavior will be used * </p> * * @param table * logging table that participated in exception. Must be instance of {@link LogTableCoreInterface}, otherwise * default suppress exception behavior will be used. * @param e * if key-value pair is not defined or value is set to FALSE/N, e will be checked and suppressable strategy * with short message can be chosen. * @return * @see {@link org.pentaho.di.core.Const#KETTLE_VARIABLES_FILE} */ public static LogExceptionBehaviourInterface getExceptionStrategy( LogTableCoreInterface table, Exception e ) { DatabaseInterfaceExtended databaseInterface = extractDatabase( table ); LogExceptionBehaviourInterface suppressableResult = suppressable; if ( databaseInterface != null && !databaseInterface.fullExceptionLog( e ) ) { suppressableResult = suppressableWithShortMessage; } String val = System.getProperty( KETTLE_GLOBAL_PROP_NAME ); // with a small penalty for backward compatibility if ( val == null ) { // same as before return suppressableResult; } ValueString sVal = new ValueString( val ); return sVal.getBoolean() ? throwable : suppressableResult; } private static DatabaseInterfaceExtended extractDatabase( LogTableCoreInterface table ) { DatabaseInterfaceExtended result = null; if ( table != null && table.getDatabaseMeta() != null ) { DatabaseInterface databaseInterface = table.getDatabaseMeta().getDatabaseInterface(); result = databaseInterface instanceof DatabaseInterfaceExtended ? (DatabaseInterfaceExtended) databaseInterface : null; } return result; } /** * Throw exception back to caller, this will be logged somewhere else. */ private static class ThrowableBehaviour implements LogExceptionBehaviourInterface { @Override public void registerException( LogChannelInterface log, Class<?> packageClass, String key, String... parameters ) throws KettleDatabaseException { throw new KettleDatabaseException( BaseMessages.getString( packageClass, key, parameters ) ); } @Override public void registerException( LogChannelInterface log, Exception e, Class<?> packageClass, String key, String... parameters ) throws KettleDatabaseException { throw new KettleDatabaseException( BaseMessages.getString( packageClass, key, parameters ), e ); } } /** * Suppress exception, but still add a log record about it */ private static class SuppressBehaviour implements LogExceptionBehaviourInterface { @Override public void registerException( LogChannelInterface log, Class<?> packageClass, String key, String... parameters ) { log.logError( BaseMessages.getString( packageClass, key, parameters ) ); } @Override public void registerException( LogChannelInterface log, Exception e, Class<?> packageClass, String key, String... parameters ) throws KettleDatabaseException { log.logError( BaseMessages.getString( packageClass, key, parameters ), e ); } } /** * Suppress exception, but still add a log record about it without stacktrace */ private static class SuppressableWithShortMessage extends SuppressBehaviour { @Override public void registerException( LogChannelInterface log, Exception e, Class<?> packageClass, String key, String... parameters ) throws KettleDatabaseException { registerException( log, packageClass, key, parameters ); log.logError( e.getMessage() ); } } }