1 /*
2 * #%L
3 * JulLog.java - mongodb-async-driver - Allanbank Consulting, Inc.
4 * %%
5 * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6 * %%
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * #L%
19 */
20 package com.allanbank.mongodb.util.log;
21
22 import java.util.logging.Level;
23 import java.util.logging.LogRecord;
24 import java.util.logging.Logger;
25
26 /**
27 * JulLog is the simplified logging implementation for Java Util Logging.
28 *
29 * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
30 * mutated in incompatible ways between any two releases of the driver.
31 * @copyright 2014, Allanbank Consulting, Inc., All Rights Reserved
32 */
33 public class JulLog extends AbstractLog {
34
35 /** The delegate for the log to a {@link Logger}. */
36 private final Logger myDelegate;
37
38 /**
39 * Creates a new {@link JulLog}.
40 *
41 * @param clazz
42 * The class for the logger.
43 */
44 protected JulLog(final Class<?> clazz) {
45 myDelegate = Logger.getLogger(clazz.getName());
46 }
47
48 /**
49 * {@inheritDoc}
50 * <p>
51 * Overridden to create a {@link LogRecord} based on the log information.
52 * </p>
53 *
54 * @see Log#log(Level, Throwable, String, Object[])
55 */
56 @Override
57 protected final void doLog(final Level level, final Throwable thrown,
58 final String template, final Object... args) {
59 if (myDelegate.isLoggable(level)) {
60
61 final Thread currentThread = Thread.currentThread();
62 final LogRecord record = new LogRecord(level,
63 format(template, args));
64 record.setLoggerName(myDelegate.getName());
65 record.setThrown(thrown);
66 record.setThreadID((int) Thread.currentThread().getId());
67
68 // Note the name of the class is the AbstractLog which is where all
69 // of
70 // the public log methods are implemented.
71 boolean lookingForThisClass = true;
72 for (final StackTraceElement element : currentThread
73 .getStackTrace()) {
74 final String className = element.getClassName();
75
76 // Find this method (and maybe others from this class).
77 if (lookingForThisClass) {
78 lookingForThisClass = !CLASS_NAME.equals(className);
79 }
80 else {
81 // And back until we are past this class.
82 if (!CLASS_NAME.equals(className)) {
83 record.setSourceClassName(className);
84 record.setSourceMethodName(element.getMethodName());
85 break;
86 }
87 }
88 }
89
90 // Finally - log it.
91 myDelegate.log(record);
92 }
93 }
94
95 /**
96 * Formats the message to be logged.
97 *
98 * @param template
99 * The template for the message.
100 * @param args
101 * The arguments to use to replace the {@value #REPLACE_TOKEN}
102 * entries in the template.
103 * @return The formatted message.
104 */
105 private String format(final String template, final Object[] args) {
106 String result = template;
107 if ((args != null) && (args.length > 0)
108 && (template.indexOf(REPLACE_TOKEN) >= 0)) {
109
110 final StringBuilder builder = new StringBuilder(template.length());
111 for (final Object arg : args) {
112 final int index = result.indexOf(REPLACE_TOKEN);
113 if (index < 0) {
114 break;
115 }
116
117 builder.append(result.substring(0, index));
118 builder.append(arg);
119 result = result.substring(index + 2);
120 }
121
122 builder.append(result);
123 result = builder.toString();
124 }
125 return result;
126 }
127
128 }