diff options
-rw-r--r-- | src/main/java/de/romjaki/logger/EventHandler.java | 15 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/Level.java | 18 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/LogEvent.java | 26 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/LogHandler.java | 8 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/LoggedEvent.java | 23 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/Logger.java | 212 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/impl/FileLogger.java | 27 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/impl/LoggerImpl.java | 12 | ||||
-rw-r--r-- | src/main/java/de/romjaki/logger/impl/StreamLogger.java | 38 |
9 files changed, 379 insertions, 0 deletions
diff --git a/src/main/java/de/romjaki/logger/EventHandler.java b/src/main/java/de/romjaki/logger/EventHandler.java new file mode 100644 index 0000000..8a6855c --- /dev/null +++ b/src/main/java/de/romjaki/logger/EventHandler.java @@ -0,0 +1,15 @@ +package de.romjaki.logger; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; + +/** + * Created by RGR on 17.08.2017. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({METHOD}) +public @interface EventHandler { +} diff --git a/src/main/java/de/romjaki/logger/Level.java b/src/main/java/de/romjaki/logger/Level.java new file mode 100644 index 0000000..38310ab --- /dev/null +++ b/src/main/java/de/romjaki/logger/Level.java @@ -0,0 +1,18 @@ +package de.romjaki.logger; + +/** + * Created by RGR on 17.08.2017. + */ +public enum Level { + ALL, + FAILURE, + ERROR, + WARNING, + INFO, + DEBUG, + OFF; + + public boolean logs(Level level) { + return this.ordinal() <= level.ordinal(); + } +} diff --git a/src/main/java/de/romjaki/logger/LogEvent.java b/src/main/java/de/romjaki/logger/LogEvent.java new file mode 100644 index 0000000..e62742c --- /dev/null +++ b/src/main/java/de/romjaki/logger/LogEvent.java @@ -0,0 +1,26 @@ +package de.romjaki.logger; + +/** + * Created by RGR on 17.08.2017. + */ +public abstract class LogEvent { + + boolean interrupted = false; + Class<?> actor; + + public LogEvent(Class<?> actor) { + this.actor = actor; + } + + public void interrupt() { + interrupted = true; + } + + public Class<?> getActor() { + return actor; + } + + public boolean isInterrupted() { + return interrupted; + } +} diff --git a/src/main/java/de/romjaki/logger/LogHandler.java b/src/main/java/de/romjaki/logger/LogHandler.java new file mode 100644 index 0000000..5f23e11 --- /dev/null +++ b/src/main/java/de/romjaki/logger/LogHandler.java @@ -0,0 +1,8 @@ +package de.romjaki.logger; + + +/** + * Created by RGR on 17.08.2017. + */ +public interface LogHandler { +} diff --git a/src/main/java/de/romjaki/logger/LoggedEvent.java b/src/main/java/de/romjaki/logger/LoggedEvent.java new file mode 100644 index 0000000..143ab0c --- /dev/null +++ b/src/main/java/de/romjaki/logger/LoggedEvent.java @@ -0,0 +1,23 @@ +package de.romjaki.logger; + +/** + * Created by RGR on 17.08.2017. + */ +public class LoggedEvent extends LogEvent { + private final Level level; + private final String text; + + public LoggedEvent(Class<?> clazz, Level level, String text) { + super(clazz); + this.level = level; + this.text = text; + } + + public Level getLevel() { + return level; + } + + public String getText() { + return text; + } +} diff --git a/src/main/java/de/romjaki/logger/Logger.java b/src/main/java/de/romjaki/logger/Logger.java new file mode 100644 index 0000000..bec0121 --- /dev/null +++ b/src/main/java/de/romjaki/logger/Logger.java @@ -0,0 +1,212 @@ +package de.romjaki.logger; + +import de.romjaki.logger.impl.LoggerImpl; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static de.romjaki.logger.Level.*; + +/** + * Created by RGR on 17.08.2017. + */ +public abstract class Logger { + private static String format = "[{LEVEL}][{DATE}]{NAME}: {TEXT}"; + private static ConcurrentMap<String, Logger> loggers = new ConcurrentHashMap<>(); + private String name; + private Level logLevel = WARNING; + private Set<LogHandler> handlers = new HashSet<>(); + private DateFormat localDateFormat = new SimpleDateFormat(format); + + protected Logger() { + this(""); + } + + protected Logger(String name) { + this.name = name; + } + + public static Logger getLogger(String name) { + return loggers.computeIfAbsent(name.toLowerCase(), LoggerImpl::new); + } + + public static Logger getLogger() { + return getLogger(getCallingClass().getSimpleName()); + } + + private static Class<?> getCallingClass() { + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + for (int i = 1; i < trace.length; i++) { + StackTraceElement ste = trace[i]; + if (!ste.getClassName().equals(Logger.class.getName()) && ste.getClassName().indexOf("java.lang.Thread") != 0) { + try { + return Class.forName(ste.getClassName()); + } catch (ClassNotFoundException e) { // should never happen. THIS CLASS FUCKING CALLED US! + e.printStackTrace(); + } + } + } + return Logger.class; // Apparently we called ourself since we traversed the entire stack without finding any other classes + } + + public void setDateFormat(String newFormat) { + setDateFormat(new SimpleDateFormat(newFormat)); + } + + private void setDateFormat(DateFormat dateFormat) { + this.localDateFormat = dateFormat; + } + + public void addEventHandler(LogHandler handler) { + handlers.add(handler); + } + + public Level getLogLevel() { + return logLevel; + } + + public void setLogLevel(Level logLevel) { + this.logLevel = logLevel; + } + + public String getName() { + return name; + } + + public void log(Level level, String text) { + if (logLevel.logs(level)) { + doLog(level, text); + } + } + + public void logf(Level level, String format, Object... fillIn) { + log(level, String.format(format, fillIn)); + } + + public void info(String text) { + log(INFO, text); + } + + public void infof(String format, Object... fillIn) { + logf(INFO, format, fillIn); + } + + public void warn(String text) { + log(WARNING, text); + } + + public void warnf(String format, Object... fillIn) { + logf(WARNING, format, fillIn); + } + + public void debug(String text) { + log(DEBUG, text); + } + + public void debugf(String format, Object... fillIn) { + logf(DEBUG, format, fillIn); + } + + public void error(String text) { + log(ERROR, text); + } + + public void errorf(String format, Object... fillIn) { + logf(ERROR, format, fillIn); + } + + public void failure(String text) { + log(FAILURE, text); + } + + public void failuref(String format, Object... fillIn) { + logf(Level.FAILURE, format, fillIn); + } + + public PrintStream getAsPrintStream() { + return getAsPrintStream(ALL); + } + + public PrintStream getAsPrintStream(Level level) { + return getAsPrintStream(level, System.lineSeparator()); + } + + public PrintStream getAsPrintStream(Level level, String sep) { + return new PrintStream(new OutputStream() { + StringBuffer buffer = new StringBuffer(); + + final Object locker = new Object(); + + @Override + public void write(int b) throws IOException { + char c = (char) b; + synchronized (locker) { + buffer.append(c); + if (buffer.indexOf(sep) != -1) { + String[] splits = buffer.toString().split(sep, 2); + log(level, splits[0]); + if (splits.length > 1) { + buffer = new StringBuffer(splits[1].replace(sep, "")); + } else { + buffer = new StringBuffer(); + } + } + } + } + }, true); + } + + public void exception(Throwable t) { + t.printStackTrace(getAsPrintStream(ERROR)); + } + + private void doLog(Level level, String text) { + LogEvent event = new LoggedEvent(getCallingClass(), level, text); + dispatchEvent(event); + if (!event.isInterrupted()) { + println(format + .replace("{LEVEL}", level.name()) + .replace("{DATE}", localDateFormat.format(new Date())) + .replace("{NAME}", name != null ? name : "") + .replace("{TEXT}", text)); + } + } + + protected void println(String text) { + print(text + System.lineSeparator()); + } + + protected abstract void print(String text); + + protected void dispatchEvent(LogEvent event) { + handlers.forEach(handler -> dispatchEvent(event, handler)); + } + + protected void dispatchEvent(LogEvent event, LogHandler handler) { + for (Method method : handler.getClass().getMethods()) { + invokeSingle(method, event, handler); + } + } + + private void invokeSingle(Method method, LogEvent event, LogHandler handler) { + if (method.isAnnotationPresent(EventHandler.class)) { + Class<?>[] args = method.getParameterTypes(); + if (args.length == 1 && args[0].isInstance(event)) { + try { + method.invoke(handler, event); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } + +} diff --git a/src/main/java/de/romjaki/logger/impl/FileLogger.java b/src/main/java/de/romjaki/logger/impl/FileLogger.java new file mode 100644 index 0000000..b7c8f3f --- /dev/null +++ b/src/main/java/de/romjaki/logger/impl/FileLogger.java @@ -0,0 +1,27 @@ +package de.romjaki.logger.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +public class FileLogger extends StreamLogger { + public FileLogger(String name, File file) throws IOException { + super(name, new FileOutputStream(createFile(file))); + } + + public FileLogger(File file) throws IOException { + super(new FileOutputStream(createFile(file))); + } + + private static File createFile(File file) throws IOException { + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + if (!file.exists()) { + file.createNewFile(); + } + return file; + } + + +} diff --git a/src/main/java/de/romjaki/logger/impl/LoggerImpl.java b/src/main/java/de/romjaki/logger/impl/LoggerImpl.java new file mode 100644 index 0000000..e581f53 --- /dev/null +++ b/src/main/java/de/romjaki/logger/impl/LoggerImpl.java @@ -0,0 +1,12 @@ +package de.romjaki.logger.impl; + + +public class LoggerImpl extends StreamLogger { + public LoggerImpl(String name) { + super(name, System.out); + } + + public LoggerImpl() { + super(System.out); + } +} diff --git a/src/main/java/de/romjaki/logger/impl/StreamLogger.java b/src/main/java/de/romjaki/logger/impl/StreamLogger.java new file mode 100644 index 0000000..9428dfe --- /dev/null +++ b/src/main/java/de/romjaki/logger/impl/StreamLogger.java @@ -0,0 +1,38 @@ +package de.romjaki.logger.impl; + +import de.romjaki.logger.Logger; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +public class StreamLogger extends Logger { + private Writer writer; + + public StreamLogger(String name, OutputStream outputStream) { + this(name, new OutputStreamWriter(outputStream)); + } + + public StreamLogger(String name, Writer writer) { + super(name); + this.writer = writer; + } + + public StreamLogger(OutputStream outputStream) { + this(new OutputStreamWriter(outputStream)); + } + + public StreamLogger(Writer writer) { + this.writer = writer; + } + + @Override + protected void print(String text) { + try { + writer.write(text); + } catch (IOException e) { + e.printStackTrace(); + } + } +} |