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.logging.log4j.internal;
18
19 import org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.LogBuilder;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.Marker;
23 import org.apache.logging.log4j.message.Message;
24 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.apache.logging.log4j.status.StatusLogger;
26 import org.apache.logging.log4j.util.LambdaUtil;
27 import org.apache.logging.log4j.util.StackLocatorUtil;
28 import org.apache.logging.log4j.util.Supplier;
29
30
31 /**
32  * Collects data for a log event and then logs it. This class should be considered private.
33  */

34 public class DefaultLogBuilder implements LogBuilder {
35
36     private static Message EMPTY_MESSAGE = new SimpleMessage("");
37     private static final String FQCN = DefaultLogBuilder.class.getName();
38     private static final Logger LOGGER = StatusLogger.getLogger();
39
40     private final Logger logger;
41     private Level level;
42     private Marker marker;
43     private Throwable throwable;
44     private StackTraceElement location;
45     private volatile boolean inUse;
46     private long threadId;
47
48     public DefaultLogBuilder(Logger logger, Level level) {
49         this.logger = logger;
50         this.level = level;
51         this.threadId = Thread.currentThread().getId();
52         this.inUse = true;
53     }
54
55     public DefaultLogBuilder(Logger logger) {
56         this.logger = logger;
57         this.inUse = false;
58         this.threadId = Thread.currentThread().getId();
59     }
60
61     /**
62      * This method should be considered internal. It is used to reset the LogBuilder for a new log message.
63      * @param level The logging level for this event.
64      * @return This LogBuilder instance.
65      */

66     public LogBuilder reset(Level level) {
67         this.inUse = true;
68         this.level = level;
69         this.marker = null;
70         this.throwable = null;
71         this.location = null;
72         return this;
73     }
74
75     @Override
76     public LogBuilder withMarker(Marker marker) {
77         this.marker = marker;
78         return this;
79     }
80
81     @Override
82     public LogBuilder withThrowable(Throwable throwable) {
83         this.throwable = throwable;
84         return this;
85     }
86
87     @Override
88     public LogBuilder withLocation() {
89         location = StackLocatorUtil.getStackTraceElement(2);
90         return this;
91     }
92
93     @Override
94     public LogBuilder withLocation(StackTraceElement location) {
95         this.location = location;
96         return this;
97     }
98
99     public boolean isInUse() {
100         return inUse;
101     }
102
103     @Override
104     public void log(Message message) {
105         if (isValid()) {
106             logMessage(message);
107         }
108     }
109
110     @Override
111     public void log(CharSequence message) {
112         if (isValid()) {
113             logMessage(logger.getMessageFactory().newMessage(message));
114         }
115     }
116
117     @Override
118     public void log(String message) {
119         if (isValid()) {
120             logMessage(logger.getMessageFactory().newMessage(message));
121         }
122     }
123
124     @Override
125     public void log(String message, Object... params) {
126         if (isValid()) {
127             logMessage(logger.getMessageFactory().newMessage(message, params));
128         }
129     }
130
131     @Override
132     public void log(String message, Supplier<?>... params) {
133         if (isValid()) {
134             logMessage(logger.getMessageFactory().newMessage(message, LambdaUtil.getAll(params)));
135         }
136     }
137
138     @Override
139     public void log(Supplier<Message> messageSupplier) {
140         if (isValid()) {
141             logMessage(messageSupplier.get());
142         }
143     }
144
145     @Override
146     public void log(Object message) {
147         if (isValid()) {
148             logMessage(logger.getMessageFactory().newMessage(message));
149         }
150     }
151
152     @Override
153     public void log(String message, Object p0) {
154         if (isValid()) {
155             logMessage(logger.getMessageFactory().newMessage(message, p0));
156         }
157     }
158
159     @Override
160     public void log(String message, Object p0, Object p1) {
161         if (isValid()) {
162             logMessage(logger.getMessageFactory().newMessage(message, p0, p1));
163         }
164     }
165
166     @Override
167     public void log(String message, Object p0, Object p1, Object p2) {
168         if (isValid()) {
169             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2));
170         }
171     }
172
173     @Override
174     public void log(String message, Object p0, Object p1, Object p2, Object p3) {
175         if (isValid()) {
176             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3));
177         }
178     }
179
180     @Override
181     public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {
182         if (isValid()) {
183             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4));
184         }
185     }
186
187     @Override
188     public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {
189         if (isValid()) {
190             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5));
191         }
192     }
193
194     @Override
195     public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {
196         if (isValid()) {
197             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6));
198         }
199     }
200
201     @Override
202     public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
203             Object p7) {
204         if (isValid()) {
205             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7));
206         }
207     }
208
209     @Override
210     public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
211             Object p7, Object p8) {
212         if (isValid()) {
213             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7, p8));
214         }
215     }
216
217     @Override
218     public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
219             Object p7, Object p8, Object p9) {
220         if (isValid()) {
221             logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));
222         }
223     }
224
225     @Override
226     public void log() {
227         if (isValid()) {
228             logMessage(EMPTY_MESSAGE);
229         }
230     }
231
232     private void logMessage(Message message) {
233         try {
234             logger.logMessage(level, marker, FQCN, location, message, throwable);
235         } finally {
236             inUse = false;
237         }
238     }
239
240     private boolean isValid() {
241         if (!inUse) {
242             LOGGER.warn("Attempt to reuse LogBuilder was ignored. {}",
243                     StackLocatorUtil.getCallerClass(2));
244             return false ;
245         }
246         if (this.threadId != Thread.currentThread().getId()) {
247             LOGGER.warn("LogBuilder can only be used on the owning thread. {}",
248                     StackLocatorUtil.getCallerClass(2));
249             return false;
250         }
251         return true;
252     }
253 }
254