001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.message;
018
019import java.io.Serializable;
020
021import org.apache.logging.log4j.util.PerformanceSensitive;
022
023/**
024 * Implementation of the {@link MessageFactory} interface that avoids allocating temporary objects where possible.
025 * Message instances are cached in a ThreadLocal and reused when a new message is requested within the same thread.
026 * @see ParameterizedMessageFactory
027 * @see ReusableSimpleMessage
028 * @see ReusableObjectMessage
029 * @see ReusableParameterizedMessage
030 * @since 2.6
031 */
032@PerformanceSensitive("allocation")
033public final class ReusableMessageFactory implements MessageFactory2, Serializable {
034
035    /**
036     * Instance of ReusableMessageFactory..
037     */
038    public static final ReusableMessageFactory INSTANCE = new ReusableMessageFactory();
039
040    private static final long serialVersionUID = -8970940216592525651L;
041    private static ThreadLocal<ReusableParameterizedMessage> threadLocalParameterized = new ThreadLocal<>();
042    private static ThreadLocal<ReusableSimpleMessage> threadLocalSimpleMessage = new ThreadLocal<>();
043    private static ThreadLocal<ReusableObjectMessage> threadLocalObjectMessage = new ThreadLocal<>();
044
045    /**
046     * Constructs a message factory.
047     */
048    public ReusableMessageFactory() {
049        super();
050    }
051
052    private static ReusableParameterizedMessage getParameterized() {
053        ReusableParameterizedMessage result = threadLocalParameterized.get();
054        if (result == null) {
055            result = new ReusableParameterizedMessage();
056            threadLocalParameterized.set(result);
057        }
058        return result;
059    }
060
061    private static ReusableSimpleMessage getSimple() {
062        ReusableSimpleMessage result = threadLocalSimpleMessage.get();
063        if (result == null) {
064            result = new ReusableSimpleMessage();
065            threadLocalSimpleMessage.set(result);
066        }
067        return result;
068    }
069
070    private static ReusableObjectMessage getObject() {
071        ReusableObjectMessage result = threadLocalObjectMessage.get();
072        if (result == null) {
073            result = new ReusableObjectMessage();
074            threadLocalObjectMessage.set(result);
075        }
076        return result;
077    }
078
079    @Override
080    public Message newMessage(final CharSequence charSequence) {
081        ReusableSimpleMessage result = getSimple();
082        result.set(charSequence);
083        return result;
084    }
085
086    /**
087     * Creates {@link ReusableParameterizedMessage} instances.
088     *
089     * @param message The message pattern.
090     * @param params The message parameters.
091     * @return The Message.
092     *
093     * @see MessageFactory#newMessage(String, Object...)
094     */
095    @Override
096    public Message newMessage(final String message, final Object... params) {
097        return getParameterized().set(message, params);
098    }
099
100    @Override
101    public Message newMessage(final String message, final Object p0) {
102        return getParameterized().set(message, p0);
103    }
104
105    @Override
106    public Message newMessage(final String message, final Object p0, final Object p1) {
107        return getParameterized().set(message, p0, p1);
108    }
109
110    @Override
111    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2) {
112        return getParameterized().set(message, p0, p1, p2);
113    }
114
115    @Override
116    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2,
117            final Object p3) {
118        return getParameterized().set(message, p0, p1, p2, p3);
119    }
120
121    @Override
122    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
123            final Object p4) {
124        return getParameterized().set(message, p0, p1, p2, p3, p4);
125    }
126
127    @Override
128    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
129            final Object p4, final Object p5) {
130        return getParameterized().set(message, p0, p1, p2, p3, p4, p5);
131    }
132
133    @Override
134    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
135            final Object p4, final Object p5, final Object p6) {
136        return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6);
137    }
138
139    @Override
140    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
141            final Object p4, final Object p5, final Object p6, final Object p7) {
142        return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7);
143    }
144
145    @Override
146    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
147            final Object p4, final Object p5, final Object p6, final Object p7, final Object p8) {
148        return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7, p8);
149    }
150
151    @Override
152    public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3,
153            final Object p4, final Object p5, final Object p6, final Object p7, final Object p8, final Object p9) {
154        return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
155    }
156
157    /**
158     * Creates {@link ReusableSimpleMessage} instances.
159     *
160     * @param message The message String.
161     * @return The Message.
162     *
163     * @see MessageFactory#newMessage(String)
164     */
165    @Override
166    public Message newMessage(final String message) {
167        ReusableSimpleMessage result = getSimple();
168        result.set(message);
169        return result;
170    }
171
172
173    /**
174     * Creates {@link ReusableObjectMessage} instances.
175     *
176     * @param message The message Object.
177     * @return The Message.
178     *
179     * @see MessageFactory#newMessage(Object)
180     */
181    @Override
182    public Message newMessage(final Object message) {
183        ReusableObjectMessage result = getObject();
184        result.set(message);
185        return result;
186    }
187}