/** * Source code taken from {@link http://wiki.eclipse.org/EclipseLink/Foundation/Logging}. * Supports use of log4j with eclipselink. */ /******************************************************************************* * Copyright (c) 1998, 2008 Oracle. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.logging; import java.io.PrintWriter; import java.io.StringWriter; import java.text.MessageFormat; import java.util.Date; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.SimpleFormatter; import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; import org.eclipse.persistence.logging.AbstractSessionLog; import org.eclipse.persistence.logging.EclipseLinkLogRecord; /** * <p> * Print a brief summary of a TopLink LogRecord in a human readable * format. The summary will typically be 1 or 2 lines. * </p> * * @author laurent bourges (voparis) : bourges.laurent@gmail.com */ public final class FastLogFormatter extends SimpleFormatter { //~ Constants -------------------------------------------------------------------------------------------------------- /** * undefined capacity */ private final static int UNDEFINED_CAPACITY = -1; /** * initial buffer capacity = 256 chars */ private final static int INITIAL_BUFFER_CAPACITY = 256; /** * date format */ private final static String format = "{0,date} {0,time}"; /** * '(' character */ public final static char PAR_OPEN_CHAR = '('; /** * ')' character */ public final static char PAR_CLOSE_CHAR = ')'; /** * ' ' character */ public final static char SPACE_CHAR = ' '; /** * Line separator string. This is the value of the line.separator * property at the moment that the SimpleFormatter was created. */ private final static String LINE_SEPARATOR = PrivilegedAccessHelper.getLineSeparator(); //~ Members ---------------------------------------------------------------------------------------------------------- /** * computed buffer capacity */ private int adaptedBufferCapacity = UNDEFINED_CAPACITY; /** * date formatter */ private MessageFormat dateFormatter; /** * cached date instance */ private final Date dateInstance = new Date(); /** * buffer to store formatted date */ private final StringBuffer dateBuffer = new StringBuffer(64); /** * date formatter args */ private Object[] dateFormatterArgs = new Object[1]; /** * Format the given LogRecord. * @param pRecord the log record to be formatted. * @return a formatted log record */ @Override public String format(LogRecord pRecord) { if (!(pRecord instanceof EclipseLinkLogRecord)) { return super.format(pRecord); } else { final EclipseLinkLogRecord record = (EclipseLinkLogRecord) pRecord; final String message = formatMessage(record); final int capacity = (adaptedBufferCapacity == UNDEFINED_CAPACITY) ? INITIAL_BUFFER_CAPACITY : adaptedBufferCapacity + message.length(); /* * Unsynchronized & sized character buffer to avoid too much array resize operations : */ final StringBuilder sb = new StringBuilder(capacity); // local variable for performance : final char space = SPACE_CHAR; if (record.shouldPrintDate()) { synchronized (dateInstance) { // Minimize memory allocations here. dateInstance.setTime(record.getMillis()); dateFormatterArgs[0] = dateInstance; if (dateFormatter == null) { dateFormatter = new MessageFormat(format); } dateFormatter.format(dateFormatterArgs, dateBuffer, null); sb.append(dateBuffer); // reset dateBuffer content : dateBuffer.setLength(0); } sb.append(space); } if (record.getSourceClassName() != null) { sb.append(record.getSourceClassName()); } else { sb.append(record.getLoggerName()); } if (record.getSourceMethodName() != null) { sb.append(space); sb.append(record.getSourceMethodName()); } if (record.getSessionString() != null) { sb.append(space); sb.append(record.getSessionString()); } if (record.getConnection() != null) { sb.append(space); sb.append(AbstractSessionLog.CONNECTION_STRING).append(PAR_OPEN_CHAR); sb.append(String.valueOf(System.identityHashCode(record.getConnection()))).append(PAR_CLOSE_CHAR); } if (record.shouldPrintThread()) { sb.append(space); sb.append(AbstractSessionLog.THREAD_STRING).append(PAR_OPEN_CHAR); sb.append(String.valueOf(record.getThreadID())).append(PAR_CLOSE_CHAR); } sb.append(LINE_SEPARATOR); sb.append(record.getLevel().getLocalizedName()); sb.append(": "); sb.append(message); // first time, compute initial capacity : if (adaptedBufferCapacity == UNDEFINED_CAPACITY) { adaptedBufferCapacity = sb.length() + 4 - message.length(); if (CommonsLoggingSessionLog.FORCE_INTERNAL_DEBUG) { sb.append(LINE_SEPARATOR); sb.append("adaptedBufferCapacity : "); sb.append(adaptedBufferCapacity); } } /* * Log4J : not necessary : * sb.append(LINE_SEPARATOR); */ if (record.getThrown() != null) { final StringWriter sw = new StringWriter(INITIAL_BUFFER_CAPACITY); final PrintWriter pw = new PrintWriter(sw); try { if (record.getLevel().intValue() == Level.SEVERE.intValue()) { record.getThrown().printStackTrace(pw); } else if (record.getLevel().intValue() <= Level.WARNING.intValue()) { if (record.shouldLogExceptionStackTrace()) { record.getThrown().printStackTrace(pw); } else { pw.write(record.getThrown().toString()); /* * Log4J : not necessary : * pw.write(LINE_SEPARATOR); */ } } } catch (Exception e) { CommonsLoggingSessionLog.error(e); } finally { pw.close(); sb.append(sw.toString()); } } if (CommonsLoggingSessionLog.FORCE_INTERNAL_DEBUG) { final int len = sb.length(); final int cap = sb.capacity(); sb.append(LINE_SEPARATOR); sb.append("sb-Length : "); sb.append(len); sb.append(" - initial capacity : "); sb.append(capacity); sb.append(" - capacity : "); sb.append(cap); sb.append(" - resized : "); sb.append(cap > capacity); sb.append(" - overhead : "); sb.append(cap - len); } return sb.toString(); } } }