1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.log4j.spi;
18
19 import org.apache.log4j.ULogger;
20 import org.apache.log4j.helpers.MessageFormatter;
21
22
23 /**
24 * A simple implementation that logs messages of level INFO or higher on
25 * the console (<code>System.out</code>).
26 * <p>
27 * The output includes the relative time in milliseconds, thread name, level,
28 * logger name, and the message followed by the line separator for the host.
29 * In log4j terms it amounts to the "%r [%t] %level %logger - %m%n" pattern.
30 * <pre>
31 * 176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse.
32 * 225 [main] INFO examples.SortAlgo - Entered the sort method.
33 * 304 [main] INFO SortAlgo.DUMP - Dump of interger array:
34 * 317 [main] INFO SortAlgo.DUMP - Element [0] = 0
35 * 331 [main] INFO SortAlgo.DUMP - Element [1] = 1
36 * 343 [main] INFO examples.Sort - The next log statement should be an error msg.
37 * 346 [main] ERROR SortAlgo.DUMP - Tried to dump an uninitialized array.
38 * at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)
39 * at org.log4j.examples.Sort.main(Sort.java:64)
40 * 467 [main] INFO examples.Sort - Exiting main method.
41 * </pre>
42 *
43 * @author Ceki Gülcü
44 */
45 public final class SimpleULogger implements ULogger {
46
47 /**
48 * Logger name.
49 */
50 private final String loggerName;
51
52
53 /**
54 * Mark the time when this class gets loaded into memory.
55 */
56 private static long startTime = System.currentTimeMillis();
57
58 /**
59 * Line separator.
60 */
61 public static final String LINE_SEPARATOR
62 = System.getProperty("line.separator");
63
64 /**
65 * INFO string literal.
66 */
67 private static final String INFO_STR = "INFO";
68 /**
69 * WARN string literal.
70 */
71 private static final String WARN_STR = "WARN";
72 /**
73 * ERROR string literal.
74 */
75 private static final String ERROR_STR = "ERROR";
76
77 /**
78 * Constructor is private to force construction through getLogger.
79 *
80 * @param name logger name
81 */
82 private SimpleULogger(final String name) {
83 super();
84 this.loggerName = name;
85 }
86
87 /**
88 * Creates a new instance.
89 *
90 * @param name logger name
91 * @return logger.
92 */
93 public static SimpleULogger getLogger(final String name) {
94 return new SimpleULogger(name);
95 }
96
97 /**
98 * {@inheritDoc}
99 */
100 public boolean isDebugEnabled() {
101 return false;
102 }
103
104 /**
105 * {@inheritDoc}
106 */
107 public void debug(final Object msg) {
108 // NOP
109 }
110
111 /**
112 * {@inheritDoc}
113 */
114 public void debug(final Object parameterizedMsg, final Object param1) {
115 // NOP
116 }
117
118 /**
119 * {@inheritDoc}
120 */
121 public void debug(final String parameterizedMsg,
122 final Object param1,
123 final Object param2) {
124 // NOP
125 }
126
127 /**
128 * {@inheritDoc}
129 */
130 public void debug(final Object msg, final Throwable t) {
131 // NOP
132 }
133
134 /**
135 * This is our internal implementation for logging regular (non-parameterized)
136 * log messages.
137 *
138 * @param level level
139 * @param message message
140 * @param t throwable
141 */
142 private void log(final String level,
143 final String message,
144 final Throwable t) {
145 StringBuilder buf = new StringBuilder();
146
147 long millis = System.currentTimeMillis();
148 buf.append(millis - startTime);
149
150 buf.append(" [");
151 buf.append(Thread.currentThread().getName());
152 buf.append("] ");
153
154 buf.append(level);
155 buf.append(" ");
156
157 buf.append(loggerName);
158 buf.append(" - ");
159
160 buf.append(message);
161
162 buf.append(LINE_SEPARATOR);
163
164 System.out.print(buf.toString());
165 if (t != null) {
166 t.printStackTrace(System.out);
167 }
168 System.out.flush();
169 }
170
171 /**
172 * For parameterized messages, first substitute parameters and then log.
173 *
174 * @param level level
175 * @param parameterizedMsg message pattern
176 * @param param1 param1
177 * @param param2 param2
178 */
179 private void parameterizedLog(final String level,
180 final Object parameterizedMsg,
181 final Object param1,
182 final Object param2) {
183 if (parameterizedMsg instanceof String) {
184 String msgStr = (String) parameterizedMsg;
185 msgStr = MessageFormatter.format(msgStr, param1, param2);
186 log(level, msgStr, null);
187 } else {
188 // To be failsafe, we handle the case where 'messagePattern' is not
189 // a String. Unless the user makes a mistake, this should not happen.
190 log(level, parameterizedMsg.toString(), null);
191 }
192 }
193
194 /**
195 * {@inheritDoc}
196 */
197 public boolean isInfoEnabled() {
198 return true;
199 }
200
201 /**
202 * {@inheritDoc}
203 */
204 public void info(final Object msg) {
205 log(INFO_STR, msg.toString(), null);
206 }
207
208
209 /**
210 * {@inheritDoc}
211 */
212 public void info(final Object parameterizedMsg, final Object param1) {
213 parameterizedLog(INFO_STR, parameterizedMsg, param1, null);
214 }
215
216 /**
217 * {@inheritDoc}
218 */
219 public void info(final String parameterizedMsg,
220 final Object param1,
221 final Object param2) {
222 parameterizedLog(INFO_STR, parameterizedMsg, param1, param2);
223 }
224
225 /**
226 * {@inheritDoc}
227 */
228 public void info(final Object msg, final Throwable t) {
229 log(INFO_STR, msg.toString(), t);
230 }
231
232 /**
233 * {@inheritDoc}
234 */
235 public boolean isWarnEnabled() {
236 return true;
237 }
238
239 /**
240 * {@inheritDoc}
241 */
242 public void warn(final Object msg) {
243 log(WARN_STR, msg.toString(), null);
244 }
245
246 /**
247 * {@inheritDoc}
248 */
249 public void warn(final Object parameterizedMsg, final Object param1) {
250 parameterizedLog(WARN_STR, parameterizedMsg, param1, null);
251 }
252
253 /**
254 * {@inheritDoc}
255 */
256 public void warn(final String parameterizedMsg,
257 final Object param1,
258 final Object param2) {
259 parameterizedLog(WARN_STR, parameterizedMsg, param1, param2);
260 }
261
262 /**
263 * {@inheritDoc}
264 */
265 public void warn(final Object msg, final Throwable t) {
266 log(WARN_STR, msg.toString(), t);
267 }
268
269 /**
270 * {@inheritDoc}
271 */
272 public boolean isErrorEnabled() {
273 return true;
274 }
275
276 /**
277 * {@inheritDoc}
278 */
279 public void error(final Object msg) {
280 log(ERROR_STR, msg.toString(), null);
281 }
282
283
284 /**
285 * {@inheritDoc}
286 */
287 public void error(final Object parameterizedMsg, final Object param1) {
288 parameterizedLog(ERROR_STR, parameterizedMsg, param1, null);
289 }
290
291 /**
292 * {@inheritDoc}
293 */
294 public void error(final String parameterizedMsg,
295 final Object param1,
296 final Object param2) {
297 parameterizedLog(ERROR_STR, parameterizedMsg, param1, param2);
298 }
299
300 /**
301 * {@inheritDoc}
302 */
303 public void error(final Object msg, final Throwable t) {
304 log(ERROR_STR, msg.toString(), t);
305 }
306
307 }