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 }