/*! * Copyright 2010 - 2015 Pentaho Corporation. All rights reserved. * * 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.pentaho.di.purge; import java.io.OutputStream; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.MDC; /** * * @author TKafalas * */ public class PurgeUtilityLogger implements IPurgeUtilityLogger { static private ThreadLocal<PurgeUtilityLogger> purgeUtilityLogger = new ThreadLocal<PurgeUtilityLogger>(); static private ThreadLocal<PurgeUtilityLog> purgeUtilityLog = new ThreadLocal<PurgeUtilityLog>(); private boolean isFormalLogger; static final String CODE_LINE = "codeLine"; private PurgeUtilityLogger() { isFormalLogger = false; purgeUtilityLog.set( new PurgeUtilityLog() ); } private PurgeUtilityLogger( OutputStream outputStream, String purgePath, Level logLevel ) { purgeUtilityLog.set( new PurgeUtilityLog( outputStream, purgePath, logLevel ) ); isFormalLogger = true; getPurgeUtilityLog().setCurrentFilePath( getPurgeUtilityLog().getPurgePath() ); info( "Start Purge Utility" ); } public static void createNewInstance( OutputStream outputStream, String purgePath, Level logLevel ) { purgeUtilityLogger.set( new PurgeUtilityLogger( outputStream, purgePath, logLevel ) ); } public static PurgeUtilityLogger getPurgeUtilityLogger() { if ( purgeUtilityLogger.get() == null ) { purgeUtilityLogger.set( new PurgeUtilityLogger() ); } return purgeUtilityLogger.get(); } public void endJob() { if ( isFormalLogger ) { getPurgeUtilityLog().setCurrentFilePath( getPurgeUtilityLog().getPurgePath() ); info( "End Purge Utility" ); getPurgeUtilityLog().endJob(); } } public void setCurrentFilePath( String currentFilePath ) { if ( isFormalLogger ) { getPurgeUtilityLog().setCurrentFilePath( currentFilePath ); } } public void info( String s ) { setCodeLine(); getLogger().info( s ); } public void error( String s ) { setCodeLine(); getLogger().error( s ); } public void debug( String s ) { setCodeLine(); getLogger().debug( s ); } public void warn( String s ) { setCodeLine(); getLogger().debug( s ); } @Override public void error( Exception e ) { setCodeLine(); getLogger().error( throwableToString( e ) ); } private PurgeUtilityLog getPurgeUtilityLog() { PurgeUtilityLog currentLog = purgeUtilityLog.get(); if ( currentLog == null ) { throw new IllegalStateException( "No job started for current Thread" ); } return currentLog; } private Logger getLogger() { return (Logger) getPurgeUtilityLog().getLogger(); } public boolean hasLogger() { return ( purgeUtilityLog.get() == null ) ? false : true; } @Override public void debug( Object arg0 ) { setCodeLine(); getLogger().debug( arg0 ); } @Override public void debug( Object arg0, Throwable arg1 ) { setCodeLine(); getLogger().debug( arg0, arg1 ); } @Override public void error( Object arg0 ) { setCodeLine(); getLogger().error( arg0 ); } @Override public void error( Object arg0, Throwable arg1 ) { setCodeLine(); getLogger().error( arg0, arg1 ); } @Override public void fatal( Object arg0 ) { setCodeLine(); getLogger().fatal( arg0 ); } @Override public void fatal( Object arg0, Throwable arg1 ) { setCodeLine(); getLogger().fatal( arg0, arg1 ); } @Override public void info( Object arg0 ) { setCodeLine(); getLogger().info( arg0 ); } @Override public void info( Object arg0, Throwable arg1 ) { setCodeLine(); getLogger().info( arg0, arg1 ); } @Override public boolean isDebugEnabled() { setCodeLine(); return getLogger().isDebugEnabled(); } @Override public boolean isErrorEnabled() { setCodeLine(); return Level.ERROR.isGreaterOrEqual( getLogger().getLevel() ); } @Override public boolean isFatalEnabled() { setCodeLine(); return Level.FATAL.isGreaterOrEqual( getLogger().getLevel() ); } @Override public boolean isInfoEnabled() { setCodeLine(); return getLogger().isInfoEnabled(); } @Override public boolean isTraceEnabled() { setCodeLine(); return getLogger().isTraceEnabled(); } @Override public boolean isWarnEnabled() { setCodeLine(); return Level.WARN.isGreaterOrEqual( getLogger().getLevel() ); } @Override public void trace( Object arg0 ) { setCodeLine(); getLogger().trace( arg0 ); } @Override public void trace( Object arg0, Throwable arg1 ) { setCodeLine(); getLogger().trace( arg0, arg1 ); } @Override public void warn( Object arg0 ) { setCodeLine(); getLogger().warn( arg0 ); } @Override public void warn( Object arg0, Throwable arg1 ) { setCodeLine(); getLogger().warn( arg0, arg1 ); } private void setCodeLine() { for ( int stackLevel = 1; stackLevel < Thread.currentThread().getStackTrace().length; stackLevel++ ) { StackTraceElement ste = Thread.currentThread().getStackTrace()[stackLevel]; if ( !ste.getClassName().equals( this.getClass().getName() ) ) { MDC.put( CODE_LINE, ste.getClassName() + "." + ste.getMethodName() + ":" + ste.getLineNumber() ); break; } } } /** * Get the first 20 lines of the stack trace */ private String throwableToString( Throwable e ) { final StringBuilder result = new StringBuilder(); final String LINEFEED = "\n"; result.append( e.toString() ); result.append( LINEFEED ); int lineCount = 1; // add lines of stack trace for ( StackTraceElement element : e.getStackTrace() ) { result.append( element ); result.append( LINEFEED ); if ( lineCount++ >= 20 ) { break; } } return result.toString(); } }