org.nuiton.util.LoggingPatternFormatter Maven / Gradle / Ivy
Show all versions of nuiton-utils Show documentation
/*
* #%L
* Nuiton Utils
* %%
* Copyright (C) 2004 - 2010 CodeLutin
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
/**
* PatternFormatter.java
*
* Created: Sat Apr 20 2002
*
* @author POUSSIN Benjamin
* Copyright Code Lutin
*
*
* Mise a jour: $Date$
* par : $Author$
*/
package org.nuiton.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Formatter;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
/**
* Classe org.nuiton.logging.PatternFormatter.
*
* - n: new line
* - %: %
* - {: {
*
*
* - d: date
*
*
* Date follow the same pattern as DateFormat.
*
* Sized
*
* - o: free memory
* - O: total memory
* - t: thread id
* - p: priority level
* - c: class name
* - m: message
* - a: argument
* - e: exception
*
*
* Sized element support justify pattern.
* {[+|-]<size>[:<maxPo>]}.
* '+' is
* left justify, '-' rigth justify, size the prefered size for the element if it is not bigger.
* If maxPos option is present blanc is not add if it go up to maxPos.
*
* SubString
*
* - M: method name
*
*
* L'element SubString a les memes possibilites que le pattern justify,
* et permet en plus de suprimer une sous chaine,
* cela permet de supprimer le debut du nom d'une classe.
* Syntaxe :
* {*<substring>|[+|-]<size>[:<maxPos>]}
* {<substring>*|[+|-]<size>[:<maxPos>]}
* L'etoile represente le texte qui restera.
*/
public class LoggingPatternFormatter extends Formatter { // PatternFormatter
private static final String DEFAULT_PATTERN = "%d{yyyy-MM-dd HH:mm:ss} [free:%o{-7}|total:%O{-7}][%t][%p{7}] %c{org.nuiton.*|25} %M{15:105}: %m%n%e";
protected HashMap> arguments = null;
protected ArrayList compile = null;
protected String pattern = null;
public LoggingPatternFormatter() {
try {
arguments = new HashMap>();
initArguments();
LogManager manager = LogManager.getLogManager();
String cname = this.getClass().getName();
pattern = manager.getProperty(cname + ".pattern");
if (pattern == null)
pattern = DEFAULT_PATTERN;
compilePattern(pattern);
} catch (Exception eee) {
System.err.println("Impossible d'utiliser le PatternFormatter");
eee.printStackTrace();
throw new LoggingException(
"Exception durant l'initialisation du PatternFormatter",
eee);
}
}
/**
* Methode qui formate le record
*
* @param record FIXME
* @return FIXME
*/
public String format(LogRecord record) {
StringBuffer result = new StringBuffer();
for (Iterator i = compile.iterator(); i.hasNext(); ) {
((Argument) i.next()).toString(record, result);
}
return result.toString();
}
/**
* Si vous souhaitez ajouter des type d'argument
* Surcharger cette methode et a la fin fait un super.initArguments()
*/
protected void initArguments() {
arguments.put("d", DateArgument.class);
arguments.put("o", FreeMemoryArgument.class);
arguments.put("O", TotalMemoryArgument.class);
arguments.put("t", ThreadArgument.class);
arguments.put("p", PriorityLevelArgument.class);
arguments.put("c", ClassNameArgument.class);
arguments.put("M", MethodNameArgument.class);
arguments.put("m", MessageArgument.class);
arguments.put("e", ExceptionArgument.class);
}
/**
* Genere a partir de la chaine la liste des objet Argument.
*
* @param pattern FIXME
*/
protected void compilePattern(String pattern) {
compile = new ArrayList();
String[] match = findNextPattern(pattern);
while (!match[1].equals("")) {
compile.add(new StringArgument(match[0]));
compile.add(patternToArgument(match[1]));
match = findNextPattern(match[2]);
}
compile.add(new StringArgument(match[0]));
}
/**
* Recherche dans la chaine le prochaine pattern.
*
* @param s FIXME
* @return un tableau de 3 chaines, [0] ce qu'il y a avant le
* parttern, [1] le parttern, [2] ce qu'il y a apres le pattern.
*/
protected String[] findNextPattern(String s) {
String[] result = new String[]{"", "", ""};
if (s == null) {
return result;
}
int d = s.indexOf("%");
if (d != -1) { // il y a un %
if (d + 2 < s.length() && s.charAt(d + 2) == '{') {
int f = s.indexOf("}", d);
if (f != -1) { // il y a une pattern %c{pattern}
result[0] = s.substring(0, d);
result[1] = s.substring(d + 1, f);
result[2] = s.substring(f + 1);
} else {
throw new LoggingException("Error, { at position "
+ (d + 2) + " not terminated in :" + s);
}
} else { //pas de pattern
result[0] = s.substring(0, d);
result[1] = s.substring(d + 1, d + 2);
result[2] = s.substring(d + 2);
}
} else {
result[0] = s;
}
return result;
}
/**
* Converti un pattern en un objet Argument
*
* @param s FIXME
* @return FIXME
*/
protected Argument patternToArgument(String s) {
if (s.charAt(0) == 'n') { // new ligne
return new StringArgument("\n");
} else if (s.charAt(0) == '%') { // le caractere %
return new StringArgument("%");
} else if (s.charAt(0) == '{') { // le caractere {
return new StringArgument("{");
} else {
String code = s.substring(0, 1);
Class argumentClass = (Class) arguments.get(code);
if (argumentClass == null)
throw new LoggingException("Erreur dans le pattern '" + code
+ "' inconnu");
Argument argument;
try {
argument = (Argument) argumentClass.newInstance();
} catch (InstantiationException eee) {
throw new LoggingException(
"Erreur lors de l'instanciation de l'objet Argument: "
+ argumentClass.getName(), eee);
} catch (IllegalAccessException eee) {
throw new LoggingException(
"Erreur lors de l'instanciation de l'objet Argument: "
+ argumentClass.getName(), eee);
}
if (s.length() > 1) { // on a un pattern
argument.setPattern(s.substring(2));
}
return argument;
}
}
///////////////////////////////////////////////////////////////////////////////
//////////////////////////// Les Classes Argument /////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static protected abstract class Argument {
protected String pattern;
public Argument() {
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
abstract public StringBuffer toString(LogRecord record,
StringBuffer toAppendTo);
}
static protected class StringArgument extends Argument {
protected String s = null;
public StringArgument(String s) {
super();
this.s = s;
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
toAppendTo.append(s);
return toAppendTo;
}
}
static protected class DateArgument extends Argument {
protected SimpleDateFormat dateFormat = null;
public DateArgument() {
super();
}
public void setPattern(String pattern) {
super.setPattern(pattern);
dateFormat = new SimpleDateFormat(pattern);
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
toAppendTo.append(dateFormat.format(new Date(record.getMillis())));
return toAppendTo;
}
}
static abstract protected class SizedArgument extends Argument {
protected boolean left = true;
protected int width = 0;
protected int maxPos = -1;
public SizedArgument() {
super();
}
public void setPattern(String pattern) {
super.setPattern(pattern);
if (pattern.length() > 0) {
String[] subpattern = pattern.split(":");
pattern = subpattern[0];
char op = pattern.charAt(0);
if (pattern.charAt(0) == '+' || pattern.charAt(0) == '-') {
pattern = pattern.substring(1);
}
width = Integer.parseInt(pattern);
left = op != '-';
if (subpattern.length > 1) {
maxPos = Integer.parseInt(subpattern[1]);
}
}
}
protected StringBuffer justify(String s, StringBuffer toAppendTo) {
int blanc = width - s.length();
if (left) {
toAppendTo.append(s);
while (0 < blanc--
&& (maxPos == -1 || toAppendTo.length() < maxPos)) {
toAppendTo.append(" ");
}
} else {
while (0 < blanc--
&& (maxPos == -1 || toAppendTo.length() < maxPos)) {
toAppendTo.append(" ");
}
toAppendTo.append(s);
}
return toAppendTo;
}
}
static abstract protected class SubStringArgument extends SizedArgument {
/**
* la chaine qui doit etre supprimee
*/
protected String removeString = null;
/**
* vrai si la chaine doit etre retiree du debut, faux pour la fin
*/
protected boolean atBeginning = true;
public SubStringArgument() {
super();
}
public void setPattern(String pattern) {
String[] subpattern = pattern.split("\\|");
for (int i = 0; i < subpattern.length; i++) {
try { //on essai de voir si le pattern convient au SizedArgument
super.setPattern(subpattern[i]);
} catch (NumberFormatException eee) {
// il ne convient pas au SizedArgument
// c pour le substring
atBeginning = subpattern[i].charAt(0) != '*';
if (subpattern[i].charAt(0) == '*') {
removeString = subpattern[i].substring(1);
} else if (subpattern[i].endsWith("*")) {
removeString = subpattern[i].substring(0, subpattern[i]
.length() - 1);
}
}
}
}
protected String substring(String s) {
if (atBeginning) {
if (s.startsWith(removeString))
return s.substring(removeString.length());
} else {
if (s.endsWith(removeString))
return s.substring(0, s.length() - removeString.length());
}
return s;
}
}
static abstract protected class OctetArgument extends SizedArgument {
protected static final String[] UNITE = {"o", "Ko", "Mo", "Go", "To",
"Po"};
protected int diviseur = 1024;
public OctetArgument() {
super();
}
/**
* Methode permettant l'affichage d'un taille avec une representation
* humainement lisible.
*
* @param size la taille rendre lisible
* @param unit les unites a utiliser (les petits en premier)
* @param diviseur le diviseur entre unite (ex: 1000 ou 1024)
* @return la representation
*/
protected String toReadableSize(long size, String[] unit, int diviseur) {
int unitIndex = 0;
while (size > 99999 && unitIndex < unit.length) {
size /= diviseur;
unitIndex++;
}
String result = size + unit[unitIndex];
return result;
}
}
static protected class FreeMemoryArgument extends OctetArgument {
public FreeMemoryArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
return justify(toReadableSize(Runtime.getRuntime().freeMemory(),
UNITE, diviseur), toAppendTo);
}
}
static protected class TotalMemoryArgument extends OctetArgument {
public TotalMemoryArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
return justify(toReadableSize(Runtime.getRuntime().totalMemory(),
UNITE, diviseur), toAppendTo);
}
}
static protected class ThreadArgument extends SizedArgument {
public ThreadArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
return justify(Thread.currentThread().getName(), toAppendTo);
}
}
static protected class PriorityLevelArgument extends SizedArgument {
public PriorityLevelArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
return justify(record.getLevel().toString(), toAppendTo);
}
}
static protected class ClassNameArgument extends SubStringArgument {
public ClassNameArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
return justify(substring(record.getSourceClassName()), toAppendTo);
}
}
static protected class MethodNameArgument extends SizedArgument {
public MethodNameArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
return justify(record.getSourceMethodName(), toAppendTo);
}
}
static protected class MessageArgument extends SizedArgument {
public MessageArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
return justify(record.getMessage(), toAppendTo);
}
}
static protected class ExceptionArgument extends Argument {
public ExceptionArgument() {
super();
}
public StringBuffer toString(LogRecord record, StringBuffer toAppendTo) {
Throwable e = record.getThrown();
if (e != null) {
toAppendTo.append(e.getMessage());
toAppendTo.append("\n");
StringWriter st = new StringWriter();
e.printStackTrace(new PrintWriter(st));
toAppendTo.append(st.toString());
toAppendTo.append("\n");
}
return toAppendTo;
}
}
} // PatternFormatter