1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one * 3 * or more contributor license agreements. See the NOTICE file * 4 * distributed with this work for additional information * 5 * regarding copyright ownership. The ASF licenses this file * 6 * to you under the Apache License, Version 2.0 (the * 7 * "License"); you may not use this file except in compliance * 8 * with the License. You may obtain a copy of the License at * 9 * * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, * 13 * software distributed under the License is distributed on an * 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 15 * KIND, either express or implied. See the License for the * 16 * specific language governing permissions and limitations * 17 * under the License. * 18 */ 19 package org.apache.rat.utils; 20 21 import java.io.PrintWriter; 22 import java.io.StringWriter; 23 import java.io.Writer; 24 25 /** 26 * The definition of logging for the core. UIs are expected to provide an implementation of 27 * Log to log data to the appropriate system within the UI. 28 */ 29 public interface Log { 30 /** 31 * The log levels supported by logging. 32 */ 33 enum Level { 34 // these must be listed in order of decreasing noisiness. 35 /** Log debug only. */ 36 DEBUG, 37 /** Log info only. */ 38 INFO, 39 /** Log warn only. */ 40 WARN, 41 /** Log error only. */ 42 ERROR, 43 /** Log nothing. */ 44 OFF 45 } 46 47 static String formatLogEntry(final String message, final Throwable throwable) { 48 StringWriter writer = new StringWriter(); 49 PrintWriter pWriter = new PrintWriter(writer); 50 pWriter.print(message); 51 pWriter.print(System.lineSeparator()); 52 throwable.printStackTrace(pWriter); 53 return writer.toString(); 54 } 55 56 /** 57 * Gets the log level that is enabled. If encapsulated logger does not report level 58 * implementations should return DEBUG. 59 * @return the level that is enabled. 60 */ 61 Level getLevel(); 62 63 /** 64 * Sets the log level. 65 * Implementations may elect not to set the level dynamically. However, if the option is supported 66 * this method should be overridden. 67 * @param level the level to set. 68 */ 69 default void setLevel(Level level) { 70 warn(String.format("This logger does not support dynamically setting the log level. Setting to %s ignored.", level)); 71 } 72 73 /** 74 * Determines if the log level is enabled. 75 * @param level The level to check. 76 * @return true if the level will produce output in the log. 77 */ 78 default boolean isEnabled(Level level) { 79 return getLevel().ordinal() <= level.ordinal(); 80 } 81 82 /** 83 * Writes a message at a specific log level. 84 * @param level The log level to write at. 85 * @param message the message to write. 86 */ 87 void log(Level level, String message); 88 89 /** 90 * Writes a log message at the specified level. 91 * @param level the level to write the message at. 92 * @param message the message to write. 93 */ 94 default void log(Level level, Object message) { 95 log(level, message == null ? "NULL" : message.toString()); 96 } 97 98 /** 99 * Write a message at DEBUG level. 100 * @param message the message to write. 101 */ 102 default void debug(Object message) { 103 log(Level.DEBUG, message); 104 } 105 106 /** 107 * Write a message at INFO level. 108 * @param message the message to write. 109 */ 110 default void info(Object message) { 111 log(Level.INFO, message); 112 } 113 114 /** 115 * Write a message at WARN level. 116 * @param message the message to write. 117 */ 118 default void warn(Object message) { 119 log(Level.WARN, message); 120 } 121 122 /** 123 * Write a message at ERROR level. 124 * @param message the message to write. 125 */ 126 default void error(Object message) { 127 log(Level.ERROR, message); 128 } 129 130 /** 131 * Write a log message and report throwable stack trace at the specified log level. 132 * @param level the level to report at 133 * @param message the message for the log 134 * @param throwable the throwable 135 */ 136 default void log(Level level, String message, Throwable throwable) { 137 log(level, formatLogEntry(message, throwable)); 138 } 139 140 /** 141 * Write a log message and report throwable stack trace at the specified log level. 142 * @param level the level to report at 143 * @param message the message for the log 144 * @param throwable the throwable 145 */ 146 default void log(Level level, Object message, Throwable throwable) { 147 log(level, message == null ? "NULL" : message.toString(), throwable); 148 } 149 150 /** 151 * Write a debug message and report throwable stack trace. 152 * @param message the message for the log 153 * @param throwable the throwable 154 */ 155 default void debug(Object message, Throwable throwable) { 156 log(Level.DEBUG, message, throwable); 157 } 158 159 /** 160 * Write an info message and report throwable stack trace. 161 * @param message the message for the log 162 * @param throwable the throwable 163 */ 164 default void info(Object message, Throwable throwable) { 165 log(Level.INFO, message, throwable); 166 } 167 168 /** 169 * Write a warn message and report throwable stack trace. 170 * @param message the message for the log 171 * @param throwable the throwable 172 */ 173 default void warn(Object message, Throwable throwable) { 174 log(Level.WARN, message, throwable); 175 } 176 177 /** 178 * Write an error message and report throwable stack trace. 179 * @param message the message for the log 180 * @param throwable the throwable 181 */ 182 default void error(Object message, Throwable throwable) { 183 log(Level.ERROR, message, throwable); 184 } 185 186 /** 187 * Returns a Writer backed by this log. All messages are logged at "INFO" level. 188 * @return the Writer backed by this log. 189 */ 190 default Writer asWriter() { 191 return asWriter(Level.INFO); 192 } 193 194 /** 195 * Returns a Writer backed by this log. All messages are logged at "INFO" level. 196 * @return the Writer backed by this log. 197 * @param level the Log level to write at. 198 */ 199 default Writer asWriter(Level level) { 200 return new Writer() { 201 private StringBuilder sb = new StringBuilder(); 202 203 @Override 204 public void write(final char[] cbuf, final int off, final int len) { 205 String txt = String.copyValueOf(cbuf, off, len); 206 int pos = txt.indexOf(System.lineSeparator()); 207 if (pos == -1) { 208 sb.append(txt); 209 } else { 210 while (pos > -1) { 211 Log.this.log(level, sb.append(txt, 0, pos).toString()); 212 sb.delete(0, sb.length()); 213 txt = txt.substring(pos + 1); 214 pos = txt.indexOf(System.lineSeparator()); 215 } 216 sb.append(txt); 217 } 218 } 219 220 @Override 221 public void flush() { 222 if (sb.length() > 0) { 223 Log.this.log(level, sb.toString()); 224 } 225 sb = new StringBuilder(); 226 } 227 228 @Override 229 public void close() { 230 flush(); 231 } 232 }; 233 } 234 235 }