/*!
* 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 org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.Transform;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.slf4j.MDC;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* This class was derived from Log4j HTMLLayout.
*
* Appenders using this layout should have their encoding set to UTF-8 or UTF-16, otherwise events containing non ASCII
* characters could result in corrupted log files.
*
* @author tkafalas
*/
public class PurgeUtilityHTMLLayout extends Layout implements IPurgeUtilityLayout {
protected static final int BUF_SIZE = 256;
protected static final int MAX_CAPACITY = 1024;
protected static final String fontCss = "font-family: arial,sans-serif; font-size: x-small";
protected static final String thCss = "background: #336699; color: #FFFFFF; text-align: left";
static String TRACE_PREFIX = "<br> ";
private Level loggerLogLevel = Level.DEBUG;
// output buffer appended to when format() is invoked
private StringBuffer sbuf = new StringBuffer( BUF_SIZE );
String title = "Log4J Log Messages";
public PurgeUtilityHTMLLayout( Level loggerLogLevel ) {
super();
this.loggerLogLevel = loggerLogLevel;
}
/**
* The <b>Title</b> option takes a String value. This option sets the document title of the generated HTML document.
*
* <p>
* Defaults to 'Log4J Log Messages'.
*/
public void setTitle( String title ) {
this.title = title;
}
/**
* Returns the current value of the <b>Title</b> option.
*/
public String getTitle() {
return title;
}
/**
* Returns the content type output by this layout, i.e "text/html".
*/
public String getContentType() {
return "text/html";
}
/**
* No options to activate.
*/
public void activateOptions() {
}
public String format( LoggingEvent event ) {
Level logLevel = event.getLevel();
if ( sbuf.capacity() > MAX_CAPACITY ) {
sbuf = new StringBuffer( BUF_SIZE );
} else {
sbuf.setLength( 0 );
}
if ( showTimeColumn() ) {
DateFormat df = new SimpleDateFormat( "MM/dd/yyyy HH:mm:ss" );
Date date = new Date();
date.setTime( event.timeStamp );
String time = null;
try {
time = df.format( date );
} catch ( Exception ex ) {
LogLog.error( "Error occured while converting date.", ex );
}
sbuf.append( Layout.LINE_SEP + "<tr>" + Layout.LINE_SEP );
sbuf.append( "<td>" );
sbuf.append( Transform.escapeTags( time ) );
sbuf.append( "</td>" + Layout.LINE_SEP );
}
sbuf.append( "<td title=\"Purge File/Folder\">" );
sbuf.append( Transform.escapeTags( MDC.get( PurgeUtilityLog.FILE_KEY ) ) );
sbuf.append( "</td>" + Layout.LINE_SEP );
if ( showLevelColumn() ) {
sbuf.append( "<td title=\"Level\">" );
if ( logLevel.equals( Level.DEBUG ) ) {
sbuf.append( "<font color=\"#339933\">" );
sbuf.append( Transform.escapeTags( String.valueOf( event.getLevel() ) ) );
sbuf.append( "</font>" );
} else if ( logLevel.isGreaterOrEqual( Level.WARN ) ) {
sbuf.append( "<font color=\"#993300\"><strong>" );
sbuf.append( Transform.escapeTags( String.valueOf( event.getLevel() ) ) );
sbuf.append( "</strong></font>" );
} else {
sbuf.append( Transform.escapeTags( String.valueOf( event.getLevel() ) ) );
}
sbuf.append( "</td>" + Layout.LINE_SEP );
}
if ( showCodeLineColumn() ) {
LocationInfo locInfo = event.getLocationInformation();
sbuf.append( "<td>" );
sbuf.append( Transform.escapeTags( MDC.get( PurgeUtilityLogger.CODE_LINE ) ) );
// sbuf.append( Transform.escapeTags( locInfo.getFileName() ) );
// sbuf.append( ':' );
// sbuf.append( locInfo.getLineNumber() );
sbuf.append( "</td>" + Layout.LINE_SEP );
}
sbuf.append( "<td title=\"Message\">" );
sbuf.append( Transform.escapeTags( event.getRenderedMessage() ) );
sbuf.append( "</td>" + Layout.LINE_SEP );
sbuf.append( "</tr>" + Layout.LINE_SEP );
if ( event.getNDC() != null ) {
sbuf.append( "<tr><td bgcolor=\"#EEEEEE\" style=\"font-size : "
+ "xx-small;\" colspan=\"6\" title=\"Nested Diagnostic Context\">" );
sbuf.append( "NDC: " + Transform.escapeTags( event.getNDC() ) );
sbuf.append( "</td></tr>" + Layout.LINE_SEP );
}
String[] s = event.getThrowableStrRep();
if ( s != null ) {
sbuf.append( "<tr><td bgcolor=\"#993300\" style=\"color:White; font-size : xx-small;\" colspan=\"6\">" );
appendThrowableAsHTML( s, sbuf );
sbuf.append( "</td></tr>" + Layout.LINE_SEP );
}
return sbuf.toString();
}
void appendThrowableAsHTML( String[] s, StringBuffer sbuf ) {
if ( s != null ) {
int len = s.length;
if ( len == 0 ) {
return;
}
sbuf.append( Transform.escapeTags( s[0] ) );
sbuf.append( Layout.LINE_SEP );
for ( int i = 1; i < len; i++ ) {
sbuf.append( TRACE_PREFIX );
sbuf.append( Transform.escapeTags( s[i] ) );
sbuf.append( Layout.LINE_SEP );
}
}
}
/**
* Returns appropriate HTML headers.
*/
public String getHeader() {
StringBuffer sbuf = new StringBuffer();
sbuf.append( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
+ "\"http://www.w3.org/TR/html4/loose.dtd\">" + Layout.LINE_SEP );
sbuf.append( "<html>" + Layout.LINE_SEP );
sbuf.append( "<head>" + Layout.LINE_SEP );
sbuf.append( "<title>" + title + "</title>" + Layout.LINE_SEP );
sbuf.append( "<style type=\"text/css\">" + Layout.LINE_SEP );
sbuf.append( "<!--" + Layout.LINE_SEP );
sbuf.append( "body, table {font-family: arial,sans-serif; font-size: x-small;}" + Layout.LINE_SEP );
sbuf.append( "th {background: #336699; color: #FFFFFF; text-align: left;}" + Layout.LINE_SEP );
sbuf.append( "-->" + Layout.LINE_SEP );
sbuf.append( "</style>" + Layout.LINE_SEP );
sbuf.append( "</head>" + Layout.LINE_SEP );
sbuf.append( "<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\" style=\"" + fontCss + "\">"
+ Layout.LINE_SEP );
sbuf.append( "<hr size=\"1\" noshade>" + Layout.LINE_SEP );
sbuf.append( "Log session start time " + new Date() + "<br>" + Layout.LINE_SEP );
sbuf.append( "<br>" + Layout.LINE_SEP );
sbuf.append( "<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">"
+ Layout.LINE_SEP );
sbuf.append( "<tr style=\"" + thCss + "\">" + Layout.LINE_SEP );
if ( showTimeColumn() ) {
sbuf.append( "<th>Time</th>" + Layout.LINE_SEP );
}
sbuf.append( "<th>File/Folder</th>" + Layout.LINE_SEP );
if ( showLevelColumn() ) {
sbuf.append( "<th>Level</th>" + Layout.LINE_SEP );
}
if ( showCodeLineColumn() ) {
sbuf.append( "<th>File:Line</th>" + Layout.LINE_SEP );
}
sbuf.append( "<th>Message</th>" + Layout.LINE_SEP );
sbuf.append( "</tr>" + Layout.LINE_SEP );
return sbuf.toString();
}
/**
* Returns the appropriate HTML footers.
*/
public String getFooter() {
StringBuffer sbuf = new StringBuffer();
sbuf.append( "</table>" + Layout.LINE_SEP );
sbuf.append( "<br>" + Layout.LINE_SEP );
sbuf.append( "</body></html>" );
return sbuf.toString();
}
/**
* The HTML layout handles the throwable contained in logging events. Hence, this method return <code>false</code>.
*/
public boolean ignoresThrowable() {
return false;
}
private boolean showCodeLineColumn() {
return Level.DEBUG.isGreaterOrEqual( loggerLogLevel ) ? true : false;
}
private boolean showTimeColumn() {
return Level.DEBUG.isGreaterOrEqual( loggerLogLevel ) ? true : false;
}
private boolean showLevelColumn() {
return true;
}
}