View Javadoc
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.message;
18  
19  import java.io.Serializable;
20  
21  import org.apache.logging.log4j.util.PerformanceSensitive;
22  
23  /**
24   * Implementation of the {@link MessageFactory} interface that avoids allocating temporary objects where possible.
25   * Message instances are cached in a ThreadLocal and reused when a new message is requested within the same thread.
26   * @see ParameterizedMessageFactory
27   * @see ReusableSimpleMessage
28   * @see ReusableObjectMessage
29   * @see ReusableParameterizedMessage
30   * @since 2.6
31   */
32  @PerformanceSensitive("allocation")
33  public final class ReusableMessageFactory implements MessageFactory2, Serializable {
34  
35      /**
36       * Instance of ReusableMessageFactory..
37       */
38      public static final ReusableMessageFactory INSTANCE = new ReusableMessageFactory();
39  
40      private static final long serialVersionUID = -8970940216592525651L;
41      private static ThreadLocal<ReusableParameterizedMessage> threadLocalParameterized = new ThreadLocal<>();
42      private static ThreadLocal<ReusableSimpleMessage> threadLocalSimpleMessage = new ThreadLocal<>();
43      private static ThreadLocal<ReusableObjectMessage> threadLocalObjectMessage = new ThreadLocal<>();
44  
45      /**
46       * Constructs a message factory.
47       */
48      public ReusableMessageFactory() {
49          super();
50      }
51  
52      private static ReusableParameterizedMessage getParameterized() {
53          ReusableParameterizedMessage result = threadLocalParameterized.get();
54          if (result == null) {
55              result = new ReusableParameterizedMessage();
56              threadLocalParameterized.set(result);
57          }
58          return result.reserved ? new ReusableParameterizedMessage().reserve() : result.reserve();
59      }
60  
61      private static ReusableSimpleMessage getSimple() {
62          ReusableSimpleMessage result = threadLocalSimpleMessage.get();
63          if (result == null) {
64              result = new ReusableSimpleMessage();
65              threadLocalSimpleMessage.set(result);
66          }
67          return result;
68      }
69  
70      private static ReusableObjectMessage getObject() {
71          ReusableObjectMessage result = threadLocalObjectMessage.get();
72          if (result == null) {
73              result = new ReusableObjectMessage();
74              threadLocalObjectMessage.set(result);
75          }
76          return result;
77      }
78  
79      /**
80       * Invokes {@link Clearable#clear()} when possible.
81       * This flag is used internally to verify that a reusable message is no longer in use and
82       * can be reused.
83       * @param message the message to make available again
84       * @since 2.7
85       */
86      public static void release(final Message message) { // LOG4J2-1583
87          if (message instanceof Clearable) {
88              ((Clearable) message).clear();
89          }
90      }
91  
92      @Override
93      public Message newMessage(final CharSequence charSequence) {
94          final ReusableSimpleMessage result = getSimple();
95          result.set(charSequence);
96          return result;
97      }
98  
99      /**
100      * Creates {@link ReusableParameterizedMessage} instances.
101      *
102      * @param message The message pattern.
103      * @param params The message parameters.
104      * @return The Message.
105      *
106      * @see MessageFactory#newMessage(String, Object...)
107      */
108     @Override
109     public Message newMessage(final String message, final Object... params) {
110         return getParameterized().set(message, params);
111     }
112 
113     @Override
114     public Message newMessage(final String message, final Object p0) {
115         return getParameterized().set(message, p0);
116     }
117 
118     @Override
119     public Message newMessage(final String message, final Object p0, final Object p1) {
120         return getParameterized().set(message, p0, p1);
121     }
122 
123     @Override
124     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2) {
125         return getParameterized().set(message, p0, p1, p2);
126     }
127 
128     @Override
129     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2,
130             final Object p3) {
131         return getParameterized().set(message, p0, p1, p2, p3);
132     }
133 
134     @Override
135     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
136             final Object p4) {
137         return getParameterized().set(message, p0, p1, p2, p3, p4);
138     }
139 
140     @Override
141     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
142             final Object p4, final Object p5) {
143         return getParameterized().set(message, p0, p1, p2, p3, p4, p5);
144     }
145 
146     @Override
147     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
148             final Object p4, final Object p5, final Object p6) {
149         return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6);
150     }
151 
152     @Override
153     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
154             final Object p4, final Object p5, final Object p6, final Object p7) {
155         return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7);
156     }
157 
158     @Override
159     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
160             final Object p4, final Object p5, final Object p6, final Object p7, final Object p8) {
161         return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7, p8);
162     }
163 
164     @Override
165     public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
166             final Object p4, final Object p5, final Object p6, final Object p7, final Object p8, final Object p9) {
167         return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
168     }
169 
170     /**
171      * Creates {@link ReusableSimpleMessage} instances.
172      *
173      * @param message The message String.
174      * @return The Message.
175      *
176      * @see MessageFactory#newMessage(String)
177      */
178     @Override
179     public Message newMessage(final String message) {
180         final ReusableSimpleMessage result = getSimple();
181         result.set(message);
182         return result;
183     }
184 
185 
186     /**
187      * Creates {@link ReusableObjectMessage} instances.
188      *
189      * @param message The message Object.
190      * @return The Message.
191      *
192      * @see MessageFactory#newMessage(Object)
193      */
194     @Override
195     public Message newMessage(final Object message) {
196         final ReusableObjectMessage result = getObject();
197         result.set(message);
198         return result;
199     }
200 }