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 } 050 051 private static ReusableParameterizedMessage getParameterized() { 052 ReusableParameterizedMessage result = threadLocalParameterized.get(); 053 if (result == null) { 054 result = new ReusableParameterizedMessage(); 055 threadLocalParameterized.set(result); 056 } 057 return result.reserved ? new ReusableParameterizedMessage().reserve() : result.reserve(); 058 } 059 060 private static ReusableSimpleMessage getSimple() { 061 ReusableSimpleMessage result = threadLocalSimpleMessage.get(); 062 if (result == null) { 063 result = new ReusableSimpleMessage(); 064 threadLocalSimpleMessage.set(result); 065 } 066 return result; 067 } 068 069 private static ReusableObjectMessage getObject() { 070 ReusableObjectMessage result = threadLocalObjectMessage.get(); 071 if (result == null) { 072 result = new ReusableObjectMessage(); 073 threadLocalObjectMessage.set(result); 074 } 075 return result; 076 } 077 078 /** 079 * Invokes {@link Clearable#clear()} when possible. 080 * This flag is used internally to verify that a reusable message is no longer in use and 081 * can be reused. 082 * @param message the message to make available again 083 * @since 2.7 084 */ 085 public static void release(final Message message) { // LOG4J2-1583 086 if (message instanceof Clearable) { 087 ((Clearable) message).clear(); 088 } 089 } 090 091 @Override 092 public Message newMessage(final CharSequence charSequence) { 093 final ReusableSimpleMessage result = getSimple(); 094 result.set(charSequence); 095 return result; 096 } 097 098 /** 099 * Creates {@link ReusableParameterizedMessage} instances. 100 * 101 * @param message The message pattern. 102 * @param params The message parameters. 103 * @return The Message. 104 * 105 * @see MessageFactory#newMessage(String, Object...) 106 */ 107 @Override 108 public Message newMessage(final String message, final Object... params) { 109 return getParameterized().set(message, params); 110 } 111 112 @Override 113 public Message newMessage(final String message, final Object p0) { 114 return getParameterized().set(message, p0); 115 } 116 117 @Override 118 public Message newMessage(final String message, final Object p0, final Object p1) { 119 return getParameterized().set(message, p0, p1); 120 } 121 122 @Override 123 public Message newMessage(final String message, final Object p0, final Object p1, final Object p2) { 124 return getParameterized().set(message, p0, p1, p2); 125 } 126 127 @Override 128 public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, 129 final Object p3) { 130 return getParameterized().set(message, p0, p1, p2, p3); 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) { 136 return getParameterized().set(message, p0, p1, p2, p3, p4); 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) { 142 return getParameterized().set(message, p0, p1, p2, p3, p4, p5); 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) { 148 return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6); 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) { 154 return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7); 155 } 156 157 @Override 158 public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3, 159 final Object p4, final Object p5, final Object p6, final Object p7, final Object p8) { 160 return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7, p8); 161 } 162 163 @Override 164 public Message newMessage(final String message, final Object p0, final Object p1, final Object p2, final Object p3, 165 final Object p4, final Object p5, final Object p6, final Object p7, final Object p8, final Object p9) { 166 return getParameterized().set(message, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); 167 } 168 169 /** 170 * Creates {@link ReusableSimpleMessage} instances. 171 * 172 * @param message The message String. 173 * @return The Message. 174 * 175 * @see MessageFactory#newMessage(String) 176 */ 177 @Override 178 public Message newMessage(final String message) { 179 final ReusableSimpleMessage result = getSimple(); 180 result.set(message); 181 return result; 182 } 183 184 185 /** 186 * Creates {@link ReusableObjectMessage} instances. 187 * 188 * @param message The message Object. 189 * @return The Message. 190 * 191 * @see MessageFactory#newMessage(Object) 192 */ 193 @Override 194 public Message newMessage(final Object message) { 195 final ReusableObjectMessage result = getObject(); 196 result.set(message); 197 return result; 198 } 199}