@Pure @Override public int hashCode() { int hash = 7; hash = 83 * hash + threshold.hashCode(); hash = 83 * hash + Objects.hashCode(callerPrefix); hash = 83 * hash + Objects.hashCode(threadPrefix); hash = 83 * hash + Objects.hashCode(messageRegex); return hash; }
@Pure @Override public boolean isPotentiallyLogged(@Nonnull Level level) { return rules.matchAny(rule -> level.getValue() >= rule.getThreshold().getValue()); }
/** * Initializes the logging filter with a configuration-based logging filter. * * @throws IllegalArgumentException if a rule has an invalid level. */ @PureWithSideEffects @Initialize(target = LoggingFilter.class, dependencies = Files.class) public static void initializeLoggingFilter() throws IllegalArgumentException { if (LoggingFilter.filter.get() instanceof LevelBasedLoggingFilter) { LoggingFilter.filter.set(ConfigurationBasedLoggingFilter.with(Files.relativeToConfigurationDirectory("configs/logging.conf"), LoggingRule.with(Level.INFORMATION))); Log.verbose("Replaced the default level-based logging filter with a configuration-based logging filter."); } else { Log.verbose("Did not replace the non-default logging filter with a configuration-based logging filter."); } }
/** * Logs the given message and throwable if the configured filter accepts them. * Each dollar sign in the message is replaced with the corresponding argument. */ @Impure public static void log(@Nonnull Level level, @Nonnull CharSequence message, @Nullable Throwable throwable, @NonCaptured @Unmodified @Nonnull @NullableElements Object... arguments) { final @Nonnull LoggingFilter filter = LoggingFilter.filter.get(); if (filter.isPotentiallyLogged(level)) { final @Nonnull String caller = Caller.get(); final @Nonnull String thread = Thread.currentThread().getName(); final @Nonnull String originalMessage = message.toString(); final boolean addNoPeriod = originalMessage.endsWith(".") || originalMessage.endsWith(":") || originalMessage.endsWith("\n"); final @Nonnull String formattedMessage = Strings.format(originalMessage, arguments) + (addNoPeriod ? "" : "."); if (filter.isLogged(level, caller, thread, formattedMessage, throwable)) { logger.get().log(level, caller, thread, formattedMessage, throwable); } } }
/** * Decodes the given line and returns the corresponding rule. * * @throws IllegalArgumentException if a rule has an invalid level. */ @Pure public static @Nonnull LoggingRule decode(@Nonnull String line) throws IllegalArgumentException { final @Nonnull @NonNullableElements String[] tokens = line.split(";", 4); final @Nonnull Level threshold = Level.valueOf(tokens[0].trim().toUpperCase()); final @Nullable String callerPrefix = getNonEmpty(tokens, 1); final @Nullable String threadPrefix = getNonEmpty(tokens, 2); final @Nullable String messageRegex = getNonEmpty(tokens, 3); return new LoggingRule(threshold, callerPrefix, threadPrefix, messageRegex); }
/** * Initializes the logger with a rotating file logger. */ @PureWithSideEffects @Initialize(target = Logger.class) public static void initializeLogger() throws FileNotFoundException { if (Logger.logger.get() instanceof StandardOutputLogger) { Logger.logger.set(RotatingFileLogger.withDefaultDirectory()); Log.verbose("Replaced the default standard output logger with a rotating file logger."); } else { Log.verbose("Did not replace the non-default logger with a rotating file logger."); } }
/** * Writes the generated file to the file system and returns whether it was successful. */ @Impure @NonWrittenRecipient public final boolean write() { requireNotWritten(); try { writeOnce(); } catch (@Nonnull IOException exception) { ProcessingLog.error("A problem occurred while generating the file $.", getName()); Log.error("Problem:", exception); return false; } ProcessingLog.information("Generated the file $.", getName()); this.written = true; return true; }
/** * Reads a line from the standard input and returns it. */ @Impure private static @Nonnull String readLine() { try { final @Nullable String input = reader.readLine(); if (input == null) { throw new IOException("The end of the standard input has been reached."); } Log.information("Read the line $ from the console.", input); return input; } catch (@Nonnull IOException exception) { throw UncheckedExceptionBuilder.withCause(exception).build(); } }
@Impure @Override protected final void execute() throws Exception { Log.debugging("The initializer " + this + " begins its execution."); final long start = System.currentTimeMillis(); executeWithoutLogging(); final long end = System.currentTimeMillis(); Log.debugging("The initializer " + this + " ends its execution in " + (end - start) + " ms."); }
/** * Encodes this logging rule. */ @Pure public @Nonnull String encode() { final @Nonnull StringBuilder result = new StringBuilder(threshold.toString()); if (callerPrefix != null || threadPrefix != null || messageRegex != null) { result.append(";"); if (callerPrefix != null) { result.append(" ").append(callerPrefix); } if (threadPrefix != null || messageRegex != null) { result.append(";"); if (threadPrefix != null) { result.append(" ").append(threadPrefix); } if (messageRegex != null) { result.append("; ").append(messageRegex); } } } return result.toString(); }
/** * Returns the caller of the logging method. */ @Pure public static @Nonnull String get() { return get(index.get()); }
@Pure @Override public @Nonnull String toString() { return Strings.uppercaseFirstCharacter(name().toLowerCase()); }
/** * Initializes the default uncaught exception handler as early as possible. */ @PureWithSideEffects @Initialize(target = UtilityInitializer.class) public static void initializeDefaultUncaughtExceptionHandler() throws FileNotFoundException { // NetBeans 8.1 crashes if you use type annotations on anonymous classes and lambda expressions! Thread.setDefaultUncaughtExceptionHandler((Thread thread, Throwable throwable) -> Log.fatal("The following problem caused this thread to terminate.", throwable)); }
/** * Initializes the configuration directory with '~/.digitalid/'. */ @PureWithSideEffects @Initialize(target = Files.class, dependencies = UtilityInitializer.class) public static void initializeDirectory() throws IOException { if (!Files.directory.isSet()) { final @Nonnull @Absolute @ExistentParent File directory = Files.relativeToWorkingDirectory(System.getProperty("user.home") + "/.digitalid/"); if (directory.isDirectory() || directory.mkdir()) { Files.directory.set(directory); Log.verbose("Set the configuration directory to '~/.digitalid/'."); } else { throw new IOException("Could not create the directory '~/.digitalid/'."); } } else { Log.verbose("Did not set the configuration directory to '~/.digitalid/' because it is already set to $.", Files.directory.get().getAbsolutePath()); } }
/** * Returns whether this rule accepts the given message with the given arguments. */ @Pure public boolean accepts(@Nonnull Level level, @Nonnull String caller, @Nonnull String thread, @Nonnull String message) { return level.getValue() >= threshold.getValue() && (callerPrefix == null || caller.startsWith(callerPrefix)) && (threadPrefix == null || thread.startsWith(threadPrefix)) && (messageRegex == null || message.matches(messageRegex)); }
/** * Writes the given message to the standard output and terminates the line. * Each dollar sign in the message is replaced with the corresponding argument. */ @Impure public static void writeLine(@Nonnull CharSequence message, @NonCaptured @Unmodified @Nonnull @NullableElements Object... arguments) { final @Nonnull String formattedMessage = Strings.format(message, arguments); System.out.println(formattedMessage); Log.information("Wrote the line $ to the console.", formattedMessage); }
/** * Creates and registers this initializer with the given target and dependencies. */ protected LoggingInitializer(@NonCaptured @Modified @Nonnull Configuration<?> target, @NonCaptured @Unmodified @Nonnull @NonNullableElements Configuration<?>... dependencies) { super(target, dependencies); Log.debugging("The initializer " + this + " was loaded."); }
/** * Writes the given message to the standard output without terminating the line. * Each dollar sign in the message is replaced with the corresponding argument. */ @Impure public static void write(@Nonnull CharSequence message, @NonCaptured @Unmodified @Nonnull @NullableElements Object... arguments) { final @Nonnull String formattedMessage = Strings.format(message, arguments); System.out.print(formattedMessage); Log.information("Wrote the string $ to the console.", formattedMessage); }