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.reserved ? new ReusableParameterizedMessage().reserve() : result.reserve(); 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 /** 080 * Invokes {@link Clearable#clear()} when possible. 081 * This flag is used internally to verify that a reusable message is no longer in use and 082 * can be reused. 083 * @param message the message to make available again 084 * @since 2.7 085 */ 086 public static void release(final Message message) { // LOG4J2-1583 087 if (message instanceof Clearable) { 088 ((Clearable) message).clear(); 089 } 090 } 091 092 @Override 093 public Message newMessage(final CharSequence charSequence) { 094 final ReusableSimpleMessage result = getSimple(); 095 result.set(charSequence); 096 return result; 097 } 098 099 /** 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}