All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sta.mlogger.MLogger Maven / Gradle / Ivy

Go to download

Tool to convert CSV and XLS to XML, to transform XML and to convert XML to CSV, HTML, other text files, PDF etc., useful as command line tool and integrated in other projects.

There is a newer version: 3.119
Show newest version

package com.sta.mlogger;

import java.util.Properties;
import java.util.Stack;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.function.BiConsumer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;

import com.sta.mutils.ThrowingRunnable;

/**
 * 

Title: MLogger

*

Description: Realisierung einer Logger-Schnittstelle f?r diverse Projekte. * Gedacht ist diese Klasse als eine zentrale Stelle f?r alle Logging-Aktionen. * Durch die Registration von MLogEntries kann je nach den Anforderungen im * konkreten Projekt ein anderer (realer) Logger verwendet werden. Der * einfachste Fall ist in MLogEntry4Text gezeigt. Hier wird einfach ein * PrintWriter zur Ausgabe verwendet. Soll z. B. ein Standard-Logger benutzt * werden (k?nnte die Variante von Apache sein), mu? lediglich ein * MLogEntry4xxx (abgeleitet von MLogEntry) erzeugt werden, der im einfachsten * Fall nur die Methode MLogEntry.println(String) ?berschreibt. Eine Instanz * dieses MLogEntry4xxx ist dann beim Programmstart (vor der ersten * Logging-Aktion) beim Logger zu registrieren (addMLogEntry(MLogEntry)). Falls * bei der ersten Logging-Aktion (noch) kein MLogEntry registriert wurde, * wird ein Standard-MLogEntry (MLogEntry4Text) erzeugt und registriert. * Beim Logger k?nnen (wie bereits beschrieben) auch mehrere MLogEntries * registriert werden. Alle Logging-Aktionen werden dann an alle registrierten * MLogEntries weitergeleitet. Somit sind diese daf?r verantwortlich, * entsprechend dem LogLevel eine Selektion vorzunehmen. Die Standard-Methoden * in der Basisklasse MLogEntry bieten daf?r bereits die notwendige * Unterst?tzung. * Ab Version 1.01 wird die Ausgabe ohne Zeilenumbruch nicht mehr unterst?tzt. * Mit Version 1.21 erfolgte die Umstellung auf Java 1.8 (ff.) und erstmalige * Verwendung einer Lambda-Konstruktion, um den Text f?r auszugebende * Nachrichten erst dann zu erstellen, wenn dieser tats?chlich ben?tigt wird. * Mit Version 1.26 wird die optionale Verwendung eines Thread-Contexts als * "MDC" (Mapped Diagnostic Context) umgesetzt. * Mit Version 1.27 erfolgt die Umstellung auf Maven. * Mit Version 1.32 erfolgt die Verteilung ?ber Maven-Central. *

*

Copyright: Copyright (c) 2002-2014, 2017-2019

*

Company: >StA-Soft<

* @author StA * @version 1.34 */ public class MLogger { /** * MLogger-Version. */ public static final String VERSION = "1.34"; /** * Copyright. */ public static final String COPYRIGHT = "2002-2014, 2017-2019"; /** * Firma. */ public static final String COMPANY = ">StA-Soft<"; /** * Name des MLogger-Property-Files. */ private static final String PROP_FILENAME = "mlogger.properties"; /** * Name des optionalen System-Propertys f?r das Verzeichnis des MLogger-Property-Files. */ public static final String SYSTEM_PROPERTY_NAME = "mlogger.config.dir"; /** * Menge der registrierten MLogEntries, die f?r alle Threads gelten, f?r die * keine speziellen MLogEntries definiert wurden. */ private static Vector statMLogEntries = new Vector(); /** * Hash-Tabelle mit Vektoren mit MLogEntries, die f?r einen konkreten Thread * definiert sind. Schl?ssel ist der Thread-Name oder die Thread-Id. */ private static Hashtable statThreadEntries = new Hashtable(); /** * Maximale Anzahl an Eintr?gen in einem Stack. */ private static final int MAX_THREAD_STACK_SIZE = 100; /** * Zeitpunkt der letzten F?llstands?berpr?fung ?ber alle Stacks. */ private static long statLastFullCheck = 0; /** * Hash-Tabelle mit Stacks f?r Log-Schl?ssel zur Zeitmessung von der * Start-Log-Meldung bis zum "Ok" bzw. "Error". */ private static Hashtable statThreadStacks = new Hashtable(); //=========================================================================== /** * Eintrag in einem Stack. */ private static class ThreadStackEntry { /** * Text. */ private String myText; /** * Zeit. */ private long myTime; /** * Constructor mit Text. * @param pText Text */ public ThreadStackEntry(String pText) { myText = pText; myTime = System.currentTimeMillis(); } /** * Text ermitteln. * @return Text */ public String getText() { return myText; } /** * Zeit ermitteln. * @return Zeit */ public long getTime() { return myTime; } } //=========================================================================== /** * Version ermitteln. * @return Version */ public static String getVersion() { return VERSION; } /** * Copyright ermitteln. * @return Copyright */ public static String getCopyright() { return COPYRIGHT; } /** * Company ermitteln. * @return Company */ public static String getCompany() { return COMPANY; } //=========================================================================== /** * String f?r Einr?ckung liefern. Die Methode wurde u. a. deshalb hier * eingef?hrt und als "static" deklariert, damit sie auch von anderen Klassen * m?glichst einfach verwendet werden kann. * @param indent Anzahl der Leerzeichen * @return String aus vorgegebener Anzahl von Leerzeichen * @see #indentStrg(String, int) */ public static String indent(int indent) { StringBuilder sb = new StringBuilder(indent); for (int i = 0; i < indent; i++) { sb.append(' '); } return sb.toString(); } /** * String pStrg pro Zeile (!) um indent Leerzeichen einr?cken. Zeilenenden * werden also beachtet. Auch diese Methode wurde u. a. deshalb hier * eingef?hrt und als "static" deklariert, damit sie auch von anderen Klassen * m?glichst einfach verwendet werden kann. * @param pStrg der String, der zeilenweise "einger?ckt" werden soll * @param indent Anzahl der Leerzeichen * @return Ergebnis-String * @see #indent(int) */ public static String indentStrg(String pStrg, int indent) { StringBuilder sb = new StringBuilder(); String si = indent(indent); StringTokenizer st = new StringTokenizer(pStrg, "\n\r"); while (st.hasMoreTokens()) { sb.append(si).append(st.nextToken()).append('\n'); } return sb.toString(); } //--------------------------------------------------------------------------- /** * MLogEntry registrieren bzw. hinzuf?gen. * @param pMLogEntry ein initialisierter MLogEntry */ public static synchronized void addMLogEntry(MLogEntry pMLogEntry) { statMLogEntries.add(pMLogEntry); } /** * Anzahl der schon vorhandenen MLogEntries ermitteln. * @return die Anzahl */ public static synchronized int getMLogEntryCount() { return statMLogEntries.size(); } /** * MLogEntry an Index i ermitteln. * @param i der Index * @return der MLogEntry */ public static synchronized MLogEntry getMLogEntry(int i) { return (MLogEntry) statMLogEntries.get(i); } /** * MLogEntries als Enumeration ermitteln. * @return Enumeration der MLogEntries */ public static synchronized Enumeration getMLogEntries() { return statMLogEntries.elements(); } /** * MLogEntry an Index i entfernen. * @param i der Index */ public static synchronized void removeMLogEntry(int i) { statMLogEntries.remove(i); } /** * MLogEntry entfernen. * @param pMLogEntry ein MLogEntry, der bereits enthalten ist */ public static synchronized void removeMLogEntry(MLogEntry pMLogEntry) { statMLogEntries.remove(pMLogEntry); } //--------------------------------------------------------------------------- /** * Thread-Eintrag ermitteln. * @return Thread-Eintrag */ private static Vector getThreadEntry() { String key = Thread.currentThread().getName(); return (Vector) statThreadEntries.get(key); } /** * Pr?fen ob Thread-Eintrag vorhanden, falls nicht: anlegen. * @return Thread-Eintrag */ private static Vector checkThreadEntry() { String key = Thread.currentThread().getName(); Vector v = (Vector) statThreadEntries.get(key); if (v == null) { v = new Vector(); statThreadEntries.put(key, v); } return v; } /** * MLogEntry registrieren bzw. hinzuf?gen (thread-spezifisch). * @param pMLogEntry ein initialisierter MLogEntry */ public static synchronized void addMLogEntryTS(MLogEntry pMLogEntry) { Vector v = checkThreadEntry(); v.add(pMLogEntry); } /* public static synchronized void addMLogEntryTSx(MLogEntry pMLogEntry) { // Pr?fe, ob ein solche MLogEntry bereits (Thread-spezifisch) hinzugef?gt // wurde. Falls ja: f?ge eben diesen statt dem ?bergebenen erneut hinzu. Enumeration e = statThreadEntries.elements(); while (e.hasMoreElements()) { Vector vv = (Vector) e.nextElement(); int i = vv.indexOf(pMLogEntry); if (i >= 0) { pMLogEntry = (MLogEntry) vv.get(i); break; } } Vector v = checkThreadEntry(); v.add(pMLogEntry); } */ /** * Anzahl der schon vorhandenen MLogEntries ermitteln (thread-spezifisch). * @return die Anzahl */ public static synchronized int getMLogEntryCountTS() { Vector v = getThreadEntry(); return v != null ? v.size() : 0; } /** * MLogEntry an Index i ermitteln (thread-spezifisch). * @param i der Index * @return der MLogEntry */ public static synchronized MLogEntry getMLogEntryTS(int i) { Vector v = getThreadEntry(); return v != null ? (MLogEntry) v.get(i) : null; } /** * MLogEntries als Enumeration ermitteln (thread-spezifisch). * @return Enumeration der MLogEntries */ public static synchronized Enumeration getMLogEntriesTS() { Vector v = getThreadEntry(); return v != null ? v.elements() : null; } /** * MLogEntry an Index i entfernen (thread-spezifisch). * @param i der Index */ public static synchronized void removeMLogEntryTS(int i) { Vector v = getThreadEntry(); if (v != null) { v.remove(i); } } /** * MLogEntry entfernen (thread-spezifisch). * @param pMLogEntry ein MLogEntry, der bereits enthalten ist */ public static synchronized void removeMLogEntryTS(MLogEntry pMLogEntry) { Vector v = getThreadEntry(); if (v != null) { v.remove(pMLogEntry); } } //--------------------------------------------------------------------------- /** * Fall (2), siehe checkMagic(String). * @param s auszugebender Text * @param i Index des ":" im Text * @return ggf. manipulierter auszugebender Text */ private static String checkMagic(String s, int i) { String text = s.substring(0, i); // ohne ":" und nachfolgenden Text String add = ""; String key = Thread.currentThread().getName(); Stack stack = (Stack) statThreadStacks.get(key); if (stack != null) { if (stack.size() != 0) { // // Variante 1: // // Nur das oberste Stack-Element pr?fen, falls das passt, Zeit eintragen // und Element entfernen. // /* ThreadStackEntry entry = (ThreadStackEntry) stack.peek(); if (text.equals(entry.getText())) { stack.pop(); if (stack.size() == 0) { statThreadStacks.remove(key); } long time = System.currentTimeMillis() - entry.getTime(); add = time < 1000 ? "" + time + " ms" : time < 1000000 ? "" + ((double) time / 1000) + " s" : "" + (time / 1000) + " s"; } else { add = ""; } */ // // Variante 2: // // Den Stack von oben beginnend nach einem passenden Element // durchsuchen, falls gefunden die Zeit eintragen und dieses Element // und alle dar?ber liegenden entfernen. // int size = stack.size(); int j = size; boolean found = false; while ((j > 0) && !found) { j--; ThreadStackEntry entry = (ThreadStackEntry) stack.get(j); if (text.equals(entry.getText())) { while (size != j) { size--; stack.remove(size); } if (size == 0) { statThreadStacks.remove(key); } long time = System.currentTimeMillis() - entry.getTime(); add = time < 1000 ? "" + time + " ms" : time < 1000000 ? "" + ((double) time / 1000) + " s" : "" + (time / 1000) + " s"; found = true; } } if (!found) { add = ""; } } else { add = ""; } } else { add = ""; } s = s.substring(0, i + 2) + add + s.substring(i + 1); // Space 2x (!) return s; } /** * Pr?fen, ob der auszugebende Text (1) mit 3 Punkten ohne vorangestelltes * Leerzeichen oder (2) auf ": Ok." bzw. ": Error." endet. * Im Fall (1) wird der Text vor den 3 Punkten samt Zeitstempel registriert. * Im Fall (2) wird nach dem Textteil vor dem ":" in den registrierten Texten * gesucht und falls gefunden, die zeitliche Differenz zu dem Eintrag in den * auszugebenden Text eingef?gt, au?erdem wird der Registrierungseintrag (und * ggf. sp?ter hinzugef?gte) wieder entfernt. * @param s auszugebender Text * @return ggf. manipulierter auszugebender Text */ private static String checkMagic(String s) { String res = s; if (s != null) { int len = s.length(); if (s.endsWith("...") && (len > 3) && (s.charAt(len - 4) != ' ')) { // Anfang String text = s.substring(0, len - 3); // ohne die 3 Punkte String key = Thread.currentThread().getName(); Stack stack = (Stack) statThreadStacks.get(key); if (stack == null) { stack = new Stack(); statThreadStacks.put(key, stack); } stack.push(new ThreadStackEntry(text)); // Sicherheitspr?fung, damit der Speicher nicht voll l?uft // (auf Maximalzahl von Eintr?gen pr?fen) if (stack.size() > MAX_THREAD_STACK_SIZE) { stack.remove(0); } // Sicherheitspr?fung ?ber alle Thread-Stack-Eint?ge synchronized (statThreadStacks) { long curtime = System.currentTimeMillis(); if (statLastFullCheck < curtime - 1 * 60 * 1000) { statLastFullCheck = curtime; long time = curtime - 60 * 60 * 1000; Enumeration e = statThreadStacks.keys(); while (e.hasMoreElements()) { String k = (String) e.nextElement(); // if (!key.equals(k)) // { Stack v = (Stack) statThreadStacks.get(key); while ((v.size() != 0) && (((ThreadStackEntry) v.get(0)).getTime() < time)) { ThreadStackEntry tse = (ThreadStackEntry) v.get(0); System.out.println("MLogger: remove entry [ " + tse.getText() + " ]."); // hier explizit n?tig v.remove(0); } if (v.size() == 0) { System.out.println("MLogger: remove stack."); // hier explizit n?tig statThreadStacks.remove(k); } // } } } } } else if (s.endsWith(": Ok.") && (len > 5) && (s.charAt(len - 6) != ' ')) { res = checkMagic(s, len - 5); } else if (s.endsWith(": Error.") && (len > 8) && (s.charAt(len - 9) != ' ')) { res = checkMagic(s, len - 8); } } return res; } /** * Sicherstellen, da? wenigstens ein MLogEntry vorhanden ist. Falls keiner * vorhanden ist, wird ein Standard-MLogEntry (MLogEntry4Text) hinzugef?gt. * * Neu (ab Version 1.24 vom 17.01.2018): Falls die Datei "mlogger.properties" * im Klassenpfad und darin ein Eintrag namens "StdMLogEntry" samt Wert * gefunden wird, dann wird versucht, eine Instanz der angegebenen Klasse * zu erzeugen und auf MLogEntry zu casten. Falls dies gelingt, wird diese * Instanz als Standard-MLogEntry verwendet, andernfalls wie bisher eine * Instanz von MLogEntry4Text. * * @see #statMLogEntries * @see #addMLogEntry(MLogEntry) */ public static synchronized void checkMLogEntries() { if (statMLogEntries.size() == 0) { MLogEntry mle = null; InputStream is = null; try { // zuerst die Property-Datei im aktuellen Verzeichnis suchen try { is = new FileInputStream(PROP_FILENAME); } catch (IOException ex) { // "Can't find " + PROP_FILENAME + "." } // falls nicht gefunden: System-Property mlogger.config.dir pr?fen und falls vorhanden in diesem Verzeichnis suchen if (is == null) { String dir = System.getProperty(SYSTEM_PROPERTY_NAME); if (dir != null) { try { is = new FileInputStream(new File(dir, PROP_FILENAME)); } catch (IOException ex) { // "Can't find " + PROP_FILENAME + "." } } } // falls auch nicht gefunden, dann im Klassenpfad suchen if (is == null) { is = MLogger.class.getResourceAsStream("/" + PROP_FILENAME); } // falls gefunden: verarbeiten, sonst ohne Property-Datei weiter if (is != null) { System.out.println("Found " + PROP_FILENAME + "."); // hier explizit n?tig, da vor MLogger-Initialisierung Properties p = new Properties(); try { p.load(is); } catch (Exception ex) { System.out.println("Error loading properties: " + ex.getMessage()); // hier explizit n?tig, da vor MLogger-Initialisierung ex.printStackTrace(); // hier explizit n?tig, da vor MLogger-Initialisierung } try { String cn = p.getProperty("StdMLogEntry"); if (cn != null) { cn = cn.trim(); if (cn.length() > 0) { Class c = Class.forName(cn); mle = (MLogEntry) c.newInstance(); } } } catch (Exception ex) { System.out.println("Can't create new instance of mlogentry: " + ex.getMessage()); // hier explizit n?tig, da vor MLogger-Initialisierung ex.printStackTrace(); // hier explizit n?tig, da vor MLogger-Initialisierung } if (mle != null) { mle.init(p); } } } finally { if (is != null) { try { is.close(); } catch (IOException ioex) { } } } addMLogEntry(mle != null ? mle : new MLogEntry4Text()); } } /** * Name der Methode ermitteln, die den Logger aufgerufen hat. Dieser * Methodenname wird dann als "Ort" verwendet. * @param idx Index im StackTrace f?r Ermittlung des Methodennamen, * alt: 3, neu: 4 * @return Methodenname incl. Packages (Fehlerfall: null) */ private static String getCallerMethodName(int idx) { Throwable t = new Throwable("X"); StackTraceElement[] stes = t.getStackTrace(); /* for (int i = 0; i < stes.length; i++) { "[" + i + "] = " + stes[i].getClassName() + "." + stes[i].getMethodName() } */ // // Aufbau: // // [0] = "getCallerMethodName(int)" "getCallerMethodName(int)" // [1] = "dispatch(int, BiConsumer)" "checkLevel(int)" // [2] = "print*(int, *)" "checkxxx()" // [3] = eine der MLogger-Methoden // // => Also ist idx mal = 4 (bei normalen Ausgaben) und mal = 3 (bei checkLevel) // // Deutlich besser w?re es aber wohl, das Feld von vorne beginnen zu durchlaufen, // bis keine MLogger-Methode mehr gefunden wurde (au?er vielleicht main(...), damit die Tests dort noch funktionieren). // Au?erdem m?ssten Methoden aus dem SLF4J-SimpleLogger "?berlesen" werden, damit man dessen Aufrufstellen findet. // int i = 0; while (i < stes.length) { StackTraceElement ste = stes[i]; String cni = ste.getClassName(); if (!"com.sta.mlogger.MLogger".equals(cni)) { if (!"org.slf4j.impl.SimpleLogger".equals(cni)) { String mni = ste.getMethodName(); return cni + "." + mni; // break; } } else { String mni = ste.getMethodName(); if ("main".equals(mni)) { return cni + "." + mni; // break; } } i++; } // R?ckfall auf die urspr?ngliche Realisierung String cn = stes[idx].getClassName(); String mn = stes[idx].getMethodName(); /* int i = cn.lastIndexOf('.'); if (i >= 0) { cn = cn.substring(i + 1); } */ return cn + "." + mn; } /** * Verteilung der auszugebenden Nachricht bzw. des Message-Builders an die zust?ndigen MLogEntries. * @param pLevel vorgegebener LogLevel * @param c Consumer mit MLogEntry und Location */ private static void dispatch(int pLevel, BiConsumer c) { String location = null; // // Zuerst Thread-MLogEntries... // Vector v = getThreadEntry(); if (v != null) { int size = v.size(); for (int i = size - 1; i >= 0; i--) { MLogEntry le = (MLogEntry) v.get(i); if (location == null) { location = getCallerMethodName(4); } if (le.checkLevel(location, pLevel)) { // le.println(location, pLevel, pStrg); c.accept(le, location); } if (le.getBreakAfterOutput()) { return; } } } // // ... dann die "normalen" MLogEntries // int size = statMLogEntries.size(); for (int i = size - 1; i >= 0; i--) { MLogEntry le = (MLogEntry) statMLogEntries.get(i); if (location == null) { location = getCallerMethodName(4); } if (le.checkLevel(location, pLevel)) { // le.println(location, pLevel, pStrg); c.accept(le, location); } // "BreakAfterOutput" pr?fen (siehe obere Schleife)? } } /** * Text ausgeben. * Diese Nachricht wird an alle registrierten MLogEntries weitergereicht. * Wichtig ist, dass diese Methode immer von Methoden aus MLogger selbst * aufgerufen wird. Diese (ausrufenden) Methon m?ssen direkt von au?erhalb * aufgrufen worden sein. Auf dieser Basis wird derzeit der Ort (Methodenname) * ermittelt. * @param pLevel vorgegebener LogLevel * @param pStrg der auszugebende Text * @see #checkMLogEntries() */ private static void println(int pLevel, String pStrg) { checkMLogEntries(); String msg = checkMagic(pStrg); dispatch(pLevel, (le, location) -> le.println(location, pLevel, msg)); } /** * Text ausgeben (ohne Zeilenumbruch). * Diese Nachricht wird an alle registrierten MLogEntries weitergereicht. * Wichtig ist, dass diese Methode immer von Methoden aus MLogger selbst * aufgerufen wird. Diese (ausrufenden) Methon m?ssen direkt von au?erhalb * aufgrufen worden sein. Auf dieser Basis wird derzeit der Ort (Methodenname) * ermittelt. * @param pLevel vorgegebener LogLevel * @param pStrg der auszugebende Text * @see #checkMLogEntries() */ private static void print(int pLevel, String pStrg) { checkMLogEntries(); String msg = checkMagic(pStrg); dispatch(pLevel, (le, location) -> le.print(location, pLevel, msg)); } /** * Text bei Bedarf erstellen und unter bestimmtem Level ausgeben. * @param pLevel Level * @param mb Message-Builder */ private static void println(int pLevel, IMessageBuilder mb) { checkMLogEntries(); IMessageBuilder mb2 = mb instanceof MMessageBuilder ? mb : new MMessageBuilder(mb); dispatch(pLevel, (le, location) -> le.println(location, pLevel, mb2)); } /** * Text bei Bedarf erstellen und unter bestimmtem Level ausgeben (ohne Zeilenumbruch). * @param pLevel Level * @param mb Message-Builder */ private static void print(int pLevel, IMessageBuilder mb) { checkMLogEntries(); // doprintln(pLevel, mb instanceof MMessageBuilder ? mb : new MMessageBuilder(mb)); // === Versuch ... === IMessageBuilder mb2 = mb instanceof MMessageBuilder ? mb : new MMessageBuilder(mb); dispatch(pLevel, (le, location) -> le.print(location, pLevel, mb2)); // === ... Versuch === } /** * Pr?fen, ob eine Nachricht mit einem bestimmten Level ausgegeben w?rde. * @param pLevel Level * @return true: Nachricht w?rde ausgegeben */ private static synchronized boolean checkLevel(int pLevel) { String location = null; Enumeration e1 = statMLogEntries.elements(); while (e1.hasMoreElements()) { MLogEntry le = (MLogEntry) e1.nextElement(); if (location == null) { location = getCallerMethodName(3); } if (le.checkLevel(location, pLevel)) { return true; } } Vector v = getThreadEntry(); if (v != null) { Enumeration e2 = v.elements(); while (e2.hasMoreElements()) { MLogEntry le = (MLogEntry) e2.nextElement(); if (location == null) { location = getCallerMethodName(3); } if (le.checkLevel(location, pLevel)) { return true; } } } return false; } //--------------------------------------------------------------------------- /** * StackTrace der Exception (des "Throwable") holen und an pStrg anf?gen, * dabei wird jeweils ein "\n" zwischen den Zeilen eingef?gt (auch nach pStrg). * @param pStrg zuvor stehender Text (kann auch null sein) * @param t die Exception (das "Throwable") * @return pStrg + StackTrace */ public static String convThrowable2String(String pStrg, Throwable t) { if (t != null) { /* ByteArrayOutputStream baos = new ByteArrayOutputStream(); t.printStackTrace(new PrintStream(baos)); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); BufferedReader br = new BufferedReader(new InputStreamReader(bais)); try { String s; while ((s = br.readLine()) != null) { if (pStrg == null) { pStrg = s; } else { pStrg += "\n" + s; } } } catch (IOException e) { } */ StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw)); String s = sw.toString(); return pStrg + "\n" + s; } return pStrg; } //--------------------------------------------------------------------------- /** * Text als "Error" (Fehler) ausgeben. * Bsp.: *
   * Error (CallerMethodName): This is the given text.
   * 
* @param pStrg der auszugebende Text */ public static void err(String pStrg) { println(MLogEntry.ERROR, pStrg); } /** * Text bei Bedarf erstellen und als "Error" (Fehler) ausgeben. * @param mb Message-Builder */ public static void err(IMessageBuilder mb) { println(MLogEntry.ERROR, mb); } /** * Text und StackTrace der Exception als "Error" (Fehler) ausgeben. * Bsp.: *
   * Error (CallerMethodName): This is the given text.
   * java.lang.NullPointerException
   *     at MyClass.mash(MyClass.java:9)
   *     at MyClass.crunch(MyClass.java:6)
   *     at MyClass.main(MyClass.java:3)
   * 
* @param pStrg der auszugebende Text * @param t a throwable (exception or error), which should be shown */ public static void err(String pStrg, Throwable t) { // StackTrace der Exception holen und an pStrg anf?gen // alt: // pStrg = convThrowable2String(pStrg, t); // println(MLogEntry.ERROR, pStrg); // neu: println(MLogEntry.ERROR, () -> convThrowable2String(pStrg, t)); } /** * Text bei Bedarf erstellen und als "Error" (Fehler) ausgeben. * @param mb Message-Builder * @param t a throwable (exception or error), which should be shown */ public static void err(IMessageBuilder mb, Throwable t) { println(MLogEntry.ERROR, () -> convThrowable2String(mb.getMessage(), t)); } /** * Pr?fen ob Fehler ausgegeben w?rden. * @return true: ja */ public static boolean checkerr() { return checkLevel(MLogEntry.ERROR); } //--------------------------------------------------------------------------- /** * Text als "Warning" (Warnung) ausgeben. * Bsp.: * Warning (CallerMethodName): This is the given text. * @param pStrg der auszugebende Text */ public static void wrn(String pStrg) { println(MLogEntry.WARNING, pStrg); } /** * Text bei Bedarf erstellen und als "Warning" (Warnung) ausgeben. * @param mb Message-Builder */ public static void wrn(IMessageBuilder mb) { println(MLogEntry.WARNING, mb); } /** * Text und StackTrace der Exception als "Warning" (Warnung) ausgeben. * Bsp.: *
   * Error (CallerMethodName): This is the given text.
   * java.lang.NullPointerException
   *     at MyClass.mash(MyClass.java:9)
   *     at MyClass.crunch(MyClass.java:6)
   *     at MyClass.main(MyClass.java:3)
   * 
* @param pStrg der auszugebende Text * @param t a throwable (exception or error), which should be shown */ public static void wrn(String pStrg, Throwable t) { // StackTrace der Exception holen und an pStrg anf?gen // alt: // pStrg = convThrowable2String(pStrg, t); // println(MLogEntry.WARNING, pStrg); // neu: println(MLogEntry.WARNING, () -> convThrowable2String(pStrg, t)); } /** * Text bei Bedarf erstellen und als "Debug" (Debug-Nachricht) ausgeben. * @param mb Message-Builder * @param t a throwable (exception or error), which should be shown */ public static void wrn(IMessageBuilder mb, Throwable t) { println(MLogEntry.WARNING, () -> convThrowable2String(mb.getMessage(), t)); } /** * Pr?fen ob Warnungen ausgegeben w?rden. * @return true: ja */ public static boolean checkwrn() { return checkLevel(MLogEntry.WARNING); } //--------------------------------------------------------------------------- /** * Text als "Info" (wichtige Information) ausgeben. * Bsp.: * Info (CallerMethodName): This is the given text. * @param pStrg der auszugebende Text */ public static void inf(String pStrg) { println(MLogEntry.INFO, pStrg); } /** * Text bei Bedarf erstellen und als "Info" (wichtige Information) ausgeben. * @param mb Message-Builder */ public static void inf(IMessageBuilder mb) { println(MLogEntry.INFO, mb); } /** * Text bei Bedarf erstellen und als "Info" (wichtige Information) ausgeben. * @param pFormat Text bzw. Format-Angaben * @param pObjects Parameter-Objekte (kann auch leer/null sein) */ public static void inf(String pFormat, Object... pObjects) { println(MLogEntry.INFO, new MMessageFormater(pFormat, pObjects)); } /** * Leerzeile als "Info" (wichtige Information) ausgeben. */ public static void inf() { println(MLogEntry.INFO, ""); } /** * Pr?fen ob Infos ausgegeben w?rden. * @return true: ja */ public static boolean checkinf() { return checkLevel(MLogEntry.INFO); } //--------------------------------------------------------------------------- /** * Text als "Message" (allgemeine Nachricht) ausgeben. * Bsp.: * Message (CallerMethodName): This is the given text. * @param pStrg der auszugebende Text */ public static void msg(String pStrg) { println(MLogEntry.MESSAGE, pStrg); } /** * Text bei Bedarf erstellen und als "Message" (allgemeine Nachricht) * ausgeben. * @param mb Message-Builder */ public static void msg(IMessageBuilder mb) { println(MLogEntry.MESSAGE, mb); } /** * Text bei Bedarf erstellen und als "Message" (allgemeine Nachricht) ausgeben. * @param pFormat Text bzw. Format-Angaben * @param pObjects Parameter-Objekte (kann auch leer/null sein) */ public static void msg(String pFormat, Object... pObjects) { println(MLogEntry.MESSAGE, new MMessageFormater(pFormat, pObjects)); } /** * Leerzeile als "Message" (allgemeine Nachricht) ausgeben. */ public static void msg() { println(MLogEntry.MESSAGE, ""); } /** * Pr?fen ob Nachrichten ausgegeben w?rden. * @return true: ja */ public static boolean checkmsg() { return checkLevel(MLogEntry.MESSAGE); } //--------------------------------------------------------------------------- /** * Text als "Debug" (Debug-Nachricht) ausgeben. * Bsp.: * Debug (CallerMethodName): This is the given text. * @param pStrg der auszugebende Text */ public static void deb(String pStrg) { println(MLogEntry.DEBUG, pStrg); } /** * Text bei Bedarf erstellen und als "Debug" (Debug-Nachricht) ausgeben. * @param mb Message-Builder */ public static void deb(IMessageBuilder mb) { println(MLogEntry.DEBUG, mb); } /** * Text bei Bedarf erstellen und als "Debug" (Debug-Nachricht) ausgeben. * @param pFormat Text bzw. Format-Angaben * @param pObjects Parameter-Objekte (kann auch leer/null sein) */ public static void deb(String pFormat, Object... pObjects) { println(MLogEntry.DEBUG, new MMessageFormater(pFormat, pObjects)); } /** * Leerzeile als "Debug" (Debug-Nachricht) ausgeben. */ public static void deb() { println(MLogEntry.DEBUG, ""); } /** * Pr?fen ob Debug-Meldungen ausgegeben w?rden. * @return true: ja */ public static boolean checkdeb() { return checkLevel(MLogEntry.DEBUG); } //--------------------------------------------------------------------------- /** * Text ausgeben. * @param pStrg der auszugebende Text * @see #println() */ public static void println(String pStrg) { println(MLogEntry.ALL, pStrg); } /** * Text bei Bedarf erstellen und ausgeben. * @param mb Message-Builder */ public static void println(IMessageBuilder mb) { println(MLogEntry.ALL, mb); } /** * Text bei Bedarf erstellen und ausgeben. * @param pFormat Text bzw. Format-Angaben * @param pObjects Parameter-Objekte (kann auch leer/null sein) */ public static void println(String pFormat, Object... pObjects) { println(MLogEntry.ALL, new MMessageFormater(pFormat, pObjects)); } /** * Leerzeile ausgeben. * @see #println(String) */ public static void println() { println(MLogEntry.ALL, ""); } /** * Text ausgeben (ohne Zeilenumbruch). * @param pStrg der auszugebende Text * @see #println() */ public static void print(String pStrg) { print(MLogEntry.ALL, pStrg); } /** * Text bei Bedarf erstellen und ausgeben (ohne Zeilenumbruch). * @param mb Message-Builder */ public static void print(IMessageBuilder mb) { print(MLogEntry.ALL, mb); } /** * Text bei Bedarf erstellen und ausgeben (ohne Zeilenumbruch). * @param pFormat Text bzw. Format-Angaben * @param pObjects Parameter-Objekte (kann auch leer/null sein) */ public static void print(String pFormat, Object... pObjects) { print(MLogEntry.ALL, new MMessageFormater(pFormat, pObjects)); } /** * Pr?fen ob Text-Meldungen ausgegeben w?rden. * @return true: ja */ public static boolean checkall() { return checkLevel(MLogEntry.ALL); } //=========================================================================== /** * Ausf?hrung mit einfachem Logging. * @param pFormat Format, z. B. "%msg" * @param pMaxLevel max. Log-Level, z. B. MLogEntry.ALL * @param r Runnable * @param Exception-Typ * @throws E Exception, die ggf. geworfen wird */ public static void runWithSimpleLogging(String pFormat, int pMaxLevel, ThrowingRunnable r) throws E { MLogEntry mle = new MLogEntry4Text(); mle.setMLogFormat(pFormat); mle.setMaxLevel(pMaxLevel); mle.setBreakAfterOutput(true); MLogger.addMLogEntryTS(mle); try { r.run(); } finally { MLogger.removeMLogEntryTS(mle); } } /** * Ausf?hrung mit einfachem Logging (ALL). * @param pFormat Format, z. B. "%msg" * @param r Runnable * @param Exception-Typ * @throws E Exception, die ggf. geworfen wird */ public static void runWithSimpleLogging(String pFormat, ThrowingRunnable r) throws E { runWithSimpleLogging(pFormat, MLogEntry.ALL, r); } /** * Ausf?hrung mit einfachem Logging ("%msg"). * @param r Runnable * @param pMaxLevel max. Log-Level, z. B. MLogEntry.ALL * @param Exception-Typ * @throws E Exception, die ggf. geworfen wird */ public static void runWithSimpleLogging(int pMaxLevel, ThrowingRunnable r) throws E { runWithSimpleLogging("%msg", pMaxLevel, r); } /** * Ausf?hrung mit einfachem Logging ("%msg", ALL). * @param r Runnable * @param Exception-Typ * @throws E Exception, die ggf. geworfen wird */ public static void runWithSimpleLogging(ThrowingRunnable r) throws E { runWithSimpleLogging("%msg", MLogEntry.ALL, r); } //=========================================================================== /** * Testweise warten. * @param ms Dauer in ms */ private static void sleep(long ms) { try { Thread.sleep(ms); } catch (Exception e) { } } /** * Main-Methode zum Test der Logger-Funktionen. * @param args Dummy */ public static void main(String[] args) { // Falls ein Argument angegeben ist, handelt es sich um einen Dateinamen, // f?r den dann ein MLogEntry4File erzeugt wird. if ((args.length == 7) || (args.length == 9)) { MLogEntry4File le = new MLogEntry4File(); le.setBaseDirectory(args[0].equals(".") ? null : args[0]); le.setBaseFileName(args[1].equals(".") ? null : args[1]); le.setDateTimeSeparator(args[2].equals(".") ? null : args[2]); le.setDateTimeFormat(args[3].equals(".") ? null : args[3]); le.setIndexSeparator(args[4].equals(".") ? null : args[4]); le.setIndexFormat(args[5].equals(".") ? null : args[5]); le.setExtension(args[6].equals(".") ? null : args[6]); if (args.length == 9) { le.setMaxFileSize(args[7] == null ? -1 : new Long(args[7]).longValue()); le.setMaxFileCount(args[8] == null ? -1 : new Integer(args[8]).intValue()); } MLogger.addMLogEntryTS(le); } else if ((args.length == 1) && (args[0].equals("-test"))) { MLogger.deb("Start test..."); MLogger.getMLogEntry(0).setMaxLevel(MLogEntry.MESSAGE); Thread t1 = new Thread() { @Override public void run() { MLogEntry4File le = new MLogEntry4File(); MLogger.addMLogEntryTS(le); int i = 0; while (true) { MLogger.deb("This is Thread 1 message " + i); // sleep(1000); i++; } } }; Thread t2 = new Thread() { @Override public void run() { MLogEntry4File le = new MLogEntry4File(); MLogger.addMLogEntryTS(le); int i = 0; while (true) { MLogger.deb("This is Thread 2 message " + i); // sleep(1000); i++; } } }; t1.start(); sleep(500); t2.start(); try { System.in.read(); } catch (Exception e) { } t1.interrupt(); t2.interrupt(); } else if (args.length != 0) { MLogger.err("Invalid syntax."); MLogger.inf("Syntax: mlogger [ -test ] | [ basedir basefn datetimesep datetimefrm indexsep indexfrm ext [ maxfs maxfc ] ]"); MLogger.inf(" basedir = base directory for log files, without ending file separator ('.' = null)"); MLogger.inf(" basefn = base file name for log files, without path and without extension ('.' = null)"); MLogger.inf(" datetimesep = separator for log files between basefn and date/time ('.' = null)"); MLogger.inf(" datetimefrm = format of date and time, if used in log file name ('.' = null)"); MLogger.inf(" indexsep = separator prior index, if index is not 0 ('.' = null)"); MLogger.inf(" indexfrm = number format for index, if index is not 0 ('.' = null)"); MLogger.inf(" (\"0000\" meens 4 digits, \"####\" meens maximum 4 digits)"); MLogger.inf(" ext = extension for log files incl. '.' (only '.' = null)"); MLogger.inf(" maxfs = maximum file size (in bytes)"); MLogger.inf(" maxfc = maximum file count"); MLogger.inf("Examples:"); MLogger.inf(" mlogger d:\\temp\\dms\\vusgk2dms log _ yyyy-MM-dd-HH-mm _ 0000 .txt"); MLogger.inf(" mlogger d:\\temp\\dms\\vusgk2dms log _ yyyy-MM-dd-HH-mm _ 0000 .txt 256 3"); return; } MLogger.msg("MLogger Version " + VERSION + " Copyright (c) " + COPYRIGHT + " " + COMPANY); MLogger.msg("ThreadName = " + Thread.currentThread().getName()); MLogger.err("This is an error message (with throwable) from MLogger.", new Exception("Hallo World!")); MLogger.err("This is an error message (without throwable) from MLogger."); MLogger.wrn("This is a warning message from MLogger."); MLogger.inf("This is an information message from MLogger."); MLogger.msg("This is a 'normal' message from MLogger."); MLogger.deb("This is a debug message from MLogger."); MLogger.println("This is a message from MLogger."); MLogger.println(); MLogger.deb("CheckTime..."); sleep(10); MLogger.deb("CheckTime: Ok."); MLogger.deb("CheckTime..."); sleep(1010); MLogger.deb("CheckTime: Ok."); MLogger.deb("CheckTime1..."); MLogger.deb("CheckTime2..."); sleep(10); MLogger.deb("CheckTime2: Ok."); MLogger.deb("CheckTime3..."); sleep(100); MLogger.deb("CheckTime3: Error."); sleep(1000); MLogger.deb("CheckTime4..."); sleep(100); MLogger.deb("CheckTime4: Error."); sleep(1000); MLogger.deb("CheckTime1: Ok."); MLogger.deb("Thread-Test..."); int loglevel = MLogger.getMLogEntry(0).getMaxLevel(); MLogger.getMLogEntry(0).setMaxLevel(MLogEntry.INFO); MLogger.inf(" Create threads..."); int threadcount = 1000; Thread[] threads = new Thread[threadcount]; for (int i = 0; i < threadcount; i++) { threads[i] = new Thread() { @Override public void run() { for (int i = 0; i < 1000; i++) { MLogger.deb("This is a demo log message which should test MLogger performance in parallel mode."); } } }; } MLogger.inf(" Create threads: Ok."); MLogger.inf(" Start threads..."); for (int i = 0; i < threadcount; i++) { threads[i].start(); } MLogger.inf(" Start threads: Ok."); MLogger.inf(" Join threads..."); for (int i = 0; i < threadcount; i++) { try { threads[i].join(); } catch (Exception e) { MLogger.err("", e); } } MLogger.inf(" Join threads: Ok."); MLogger.getMLogEntry(0).setMaxLevel(loglevel); MLogger.deb("Thread-Test: Ok."); MLogger.println(); MLogger.println("LineTest..."); MLogger.print("Here comes a line input.\nInput>"); try { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = br.readLine(); MLogger.println("Result: " + line); } catch (Exception ex) { MLogger.err("", ex); } MLogger.print("Here comes a character input.\nInput>"); try { int i = System.in.read(); char ch = (char) i; MLogger.println("Result: " + ch); } catch (Exception ex) { MLogger.err("", ex); } MLogger.println("LineTest: Ok."); MLogger.println(); } //=========================================================================== /** * Dummy-Constructor. */ protected MLogger() { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy