001 /** 002 * Source code taken from {@link http://wiki.eclipse.org/EclipseLink/Foundation/Logging}. 003 * Supports use of log4j with eclipselink. 004 */ 005 /******************************************************************************* 006 * Copyright (c) 1998, 2008 Oracle. All rights reserved. 007 * This program and the accompanying materials are made available under the 008 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 009 * which accompanies this distribution. 010 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html 011 * and the Eclipse Distribution License is available at 012 * http://www.eclipse.org/org/documents/edl-v10.php. 013 * 014 * Contributors: 015 * Oracle - initial API and implementation from Oracle TopLink 016 ******************************************************************************/ 017 package org.eclipse.persistence.logging; 018 019 import java.io.PrintWriter; 020 import java.io.StringWriter; 021 import java.text.MessageFormat; 022 import java.util.Date; 023 import java.util.logging.Level; 024 import java.util.logging.LogRecord; 025 import java.util.logging.SimpleFormatter; 026 027 import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; 028 import org.eclipse.persistence.logging.AbstractSessionLog; 029 import org.eclipse.persistence.logging.EclipseLinkLogRecord; 030 031 /** 032 * <p> 033 * Print a brief summary of a TopLink LogRecord in a human readable 034 * format. The summary will typically be 1 or 2 lines. 035 * </p> 036 * 037 * @author laurent bourges (voparis) : bourges.laurent@gmail.com 038 */ 039 public final class FastLogFormatter extends SimpleFormatter { 040 041 //~ Constants -------------------------------------------------------------------------------------------------------- 042 /** 043 * undefined capacity 044 */ 045 private final static int UNDEFINED_CAPACITY = -1; 046 /** 047 * initial buffer capacity = 256 chars 048 */ 049 private final static int INITIAL_BUFFER_CAPACITY = 256; 050 /** 051 * date format 052 */ 053 private final static String format = "{0,date} {0,time}"; 054 /** 055 * '(' character 056 */ 057 public final static char PAR_OPEN_CHAR = '('; 058 /** 059 * ')' character 060 */ 061 public final static char PAR_CLOSE_CHAR = ')'; 062 /** 063 * ' ' character 064 */ 065 public final static char SPACE_CHAR = ' '; 066 /** 067 * Line separator string. This is the value of the line.separator 068 * property at the moment that the SimpleFormatter was created. 069 */ 070 private final static String LINE_SEPARATOR = PrivilegedAccessHelper.getLineSeparator(); 071 072 //~ Members ---------------------------------------------------------------------------------------------------------- 073 /** 074 * computed buffer capacity 075 */ 076 private int adaptedBufferCapacity = UNDEFINED_CAPACITY; 077 /** 078 * date formatter 079 */ 080 private MessageFormat dateFormatter; 081 /** 082 * cached date instance 083 */ 084 private final Date dateInstance = new Date(); 085 /** 086 * buffer to store formatted date 087 */ 088 private final StringBuffer dateBuffer = new StringBuffer(64); 089 /** 090 * date formatter args 091 */ 092 private Object[] dateFormatterArgs = new Object[1]; 093 094 /** 095 * Format the given LogRecord. 096 * @param pRecord the log record to be formatted. 097 * @return a formatted log record 098 */ 099 @Override 100 public String format(LogRecord pRecord) { 101 if (!(pRecord instanceof EclipseLinkLogRecord)) { 102 return super.format(pRecord); 103 } else { 104 final EclipseLinkLogRecord record = (EclipseLinkLogRecord) pRecord; 105 106 final String message = formatMessage(record); 107 108 final int capacity = (adaptedBufferCapacity == UNDEFINED_CAPACITY) ? INITIAL_BUFFER_CAPACITY : adaptedBufferCapacity + message.length(); 109 /* 110 * Unsynchronized & sized character buffer to avoid too much array resize operations : 111 */ 112 final StringBuilder sb = new StringBuilder(capacity); 113 114 // local variable for performance : 115 final char space = SPACE_CHAR; 116 117 if (record.shouldPrintDate()) { 118 synchronized (dateInstance) { 119 // Minimize memory allocations here. 120 dateInstance.setTime(record.getMillis()); 121 dateFormatterArgs[0] = dateInstance; 122 if (dateFormatter == null) { 123 dateFormatter = new MessageFormat(format); 124 } 125 dateFormatter.format(dateFormatterArgs, dateBuffer, null); 126 sb.append(dateBuffer); 127 // reset dateBuffer content : 128 dateBuffer.setLength(0); 129 } 130 sb.append(space); 131 } 132 133 if (record.getSourceClassName() != null) { 134 sb.append(record.getSourceClassName()); 135 } else { 136 sb.append(record.getLoggerName()); 137 } 138 139 if (record.getSourceMethodName() != null) { 140 sb.append(space); 141 sb.append(record.getSourceMethodName()); 142 } 143 144 if (record.getSessionString() != null) { 145 sb.append(space); 146 sb.append(record.getSessionString()); 147 } 148 149 if (record.getConnection() != null) { 150 sb.append(space); 151 sb.append(AbstractSessionLog.CONNECTION_STRING).append(PAR_OPEN_CHAR); 152 sb.append(String.valueOf(System.identityHashCode(record.getConnection()))).append(PAR_CLOSE_CHAR); 153 } 154 155 if (record.shouldPrintThread()) { 156 sb.append(space); 157 sb.append(AbstractSessionLog.THREAD_STRING).append(PAR_OPEN_CHAR); 158 sb.append(String.valueOf(record.getThreadID())).append(PAR_CLOSE_CHAR); 159 } 160 161 sb.append(LINE_SEPARATOR); 162 163 sb.append(record.getLevel().getLocalizedName()); 164 sb.append(": "); 165 sb.append(message); 166 167 // first time, compute initial capacity : 168 if (adaptedBufferCapacity == UNDEFINED_CAPACITY) { 169 adaptedBufferCapacity = sb.length() + 4 - message.length(); 170 171 if (CommonsLoggingSessionLog.FORCE_INTERNAL_DEBUG) { 172 sb.append(LINE_SEPARATOR); 173 sb.append("adaptedBufferCapacity : "); 174 sb.append(adaptedBufferCapacity); 175 } 176 } 177 178 /* 179 * Log4J : not necessary : 180 * sb.append(LINE_SEPARATOR); 181 */ 182 if (record.getThrown() != null) { 183 final StringWriter sw = new StringWriter(INITIAL_BUFFER_CAPACITY); 184 final PrintWriter pw = new PrintWriter(sw); 185 try { 186 if (record.getLevel().intValue() == Level.SEVERE.intValue()) { 187 record.getThrown().printStackTrace(pw); 188 } else if (record.getLevel().intValue() <= Level.WARNING.intValue()) { 189 if (record.shouldLogExceptionStackTrace()) { 190 record.getThrown().printStackTrace(pw); 191 } else { 192 pw.write(record.getThrown().toString()); 193 /* 194 * Log4J : not necessary : 195 * pw.write(LINE_SEPARATOR); 196 */ 197 } 198 } 199 } catch (Exception e) { 200 CommonsLoggingSessionLog.error(e); 201 } finally { 202 pw.close(); 203 sb.append(sw.toString()); 204 } 205 } 206 207 if (CommonsLoggingSessionLog.FORCE_INTERNAL_DEBUG) { 208 final int len = sb.length(); 209 final int cap = sb.capacity(); 210 sb.append(LINE_SEPARATOR); 211 sb.append("sb-Length : "); 212 sb.append(len); 213 sb.append(" - initial capacity : "); 214 sb.append(capacity); 215 sb.append(" - capacity : "); 216 sb.append(cap); 217 sb.append(" - resized : "); 218 sb.append(cap > capacity); 219 sb.append(" - overhead : "); 220 sb.append(cap - len); 221 } 222 223 return sb.toString(); 224 } 225 } 226 }