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       * Gets the log level that is enabled. If encapsulated logger does not report level
48       * implementations should return DEBUG.
49       * @return the level that is enabled.
50       */
51      Level getLevel();
52  
53      /**
54       * Sets the log level.
55       * Implementations may elect not to set the level dynamically.  However, if the option is supported
56       * this method should be overridden.
57       * @param level the level to set.
58       */
59      default void setLevel(Level level) {
60          warn(String.format("This logger does not support dynamically setting the log level.  Setting to %s ignored.", level));
61      }
62  
63      /**
64       * Determines if the log level is enabled.
65       * @param level The level to check.
66       * @return true if the level will produce output in the log.
67       */
68      default boolean isEnabled(Level level) {
69          return getLevel().ordinal() <= level.ordinal();
70      }
71  
72      /**
73       * Writes a message at a specific log level.
74       * @param level The log level to write at.
75       * @param message the message to write.
76       */
77      void log(Level level, String message);
78  
79      /**
80       * Writes a log message at the specified level.
81       * @param level the level to write the message at.
82       * @param message the message to write.
83       */
84      default void log(Level level, Object message) {
85          log(level, message == null ? "NULL" : message.toString());
86      }
87  
88      /**
89       * Write a message at DEBUG level.
90       * @param message the message to write.
91       */
92      default void debug(Object message) {
93          log(Level.DEBUG, message);
94      }
95  
96      /**
97       * Write a message at INFO level.
98       * @param message the message to write.
99       */
100     default void info(Object message) {
101         log(Level.INFO, message);
102     }
103 
104     /**
105      * Write a message at WARN level.
106      * @param message the message to write.
107      */
108     default void warn(Object message) {
109         log(Level.WARN, message);
110     }
111 
112     /**
113      * Write a message at ERROR level.
114      * @param message the message to write.
115      */
116     default void error(Object message) {
117         log(Level.ERROR, message);
118     }
119 
120     /**
121      * Write a log message and report throwable stack trace at the specified log level.
122      * @param level the level to report at
123      * @param message the message for the log
124      * @param throwable the throwable
125      */
126     default void log(Level level, String message, Throwable throwable) {
127         StringWriter writer = new StringWriter(500);
128         PrintWriter pWriter = new PrintWriter(writer);
129         pWriter.print(message);
130         pWriter.print(System.lineSeparator());
131         throwable.printStackTrace(pWriter);
132         log(level, writer.toString());
133     }
134 
135     /**
136      * Write a log message and report throwable stack trace at the specified log level.
137      * @param level the level to report at
138      * @param message the message for the log
139      * @param throwable the throwable
140      */
141     default void log(Level level, Object message, Throwable throwable) {
142         log(level, message == null ? "NULL" : message.toString(), throwable);
143     }
144 
145     /**
146      * Write a debug message and report throwable stack trace.
147      * @param message the message for the log
148      * @param throwable the throwable
149      */
150     default void debug(Object message, Throwable throwable) {
151         log(Level.DEBUG, message, throwable);
152     }
153 
154     /**
155      * Write an info message and report throwable stack trace.
156      * @param message the message for the log
157      * @param throwable the throwable
158      */
159     default void info(Object message, Throwable throwable) {
160         log(Level.INFO, message, throwable);
161     }
162 
163     /**
164      * Write a warn message and report throwable stack trace.
165      * @param message the message for the log
166      * @param throwable the throwable
167      */
168     default void warn(Object message, Throwable throwable) {
169         log(Level.WARN, message, throwable);
170     }
171 
172     /**
173      * Write an error message and report throwable stack trace.
174      * @param message the message for the log
175      * @param throwable the throwable
176      */
177     default void error(Object message, Throwable throwable) {
178         log(Level.ERROR, message, throwable);
179     }
180 
181     /**
182      * Returns a Writer backed by this log. All messages are logged at "INFO" level.
183      * @return the Writer backed by this log.
184      */
185     default Writer asWriter() {
186         return asWriter(Level.INFO);
187     }
188 
189     /**
190      * Returns a Writer backed by this log. All messages are logged at "INFO" level.
191      * @return the Writer backed by this log.
192      * @param level the Log level to write at.
193      */
194     default Writer asWriter(Level level) {
195         return new Writer() {
196             private StringBuilder sb = new StringBuilder();
197 
198             @Override
199             public void write(final char[] cbuf, final int off, final int len) {
200                 String txt = String.copyValueOf(cbuf, off, len);
201                 int pos = txt.indexOf(System.lineSeparator());
202                 if (pos == -1) {
203                     sb.append(txt);
204                 } else {
205                     while (pos > -1) {
206                         Log.this.log(level, sb.append(txt, 0, pos).toString());
207                         sb.delete(0, sb.length());
208                         txt = txt.substring(pos + 1);
209                         pos = txt.indexOf(System.lineSeparator());
210                     }
211                     sb.append(txt);
212                 }
213             }
214 
215             @Override
216             public void flush() {
217                 if (sb.length() > 0) {
218                     Log.this.log(level, sb.toString());
219                 }
220                 sb = new StringBuilder();
221             }
222 
223             @Override
224             public void close() {
225                 flush();
226             }
227         };
228     }
229 
230 }