View Javadoc
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 }