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 org.apache.logging.log4j.status.StatusLogger;
20
21 /**
22  * Creates {@link FormattedMessage} instances for {@link MessageFactory2} methods (and {@link MessageFactory} by
23  * extension.)
24  * <p>
25  * Creates {@link SimpleMessage} objects that do not retain a reference to the parameter object.
26  * </p>
27  * <p>
28  * Intended for use by the {@link StatusLogger}: this logger retains a queue of recently logged messages in memory,
29  * causing memory leaks in web applications. (LOG4J2-1176)
30  * </p>
31  * <p>
32  * This class is immutable.
33  * </p>
34  * <h4>Note to implementors</h4>
35  * <p>
36  * This class does <em>not</em> implement any {@link MessageFactory2} methods and lets the superclass funnel those calls
37  * through {@link #newMessage(String, Object...)}.
38  * </p>
39  */

40 public final class ParameterizedNoReferenceMessageFactory extends AbstractMessageFactory {
41     private static final long serialVersionUID = 5027639245636870500L;
42
43     /**
44      * Message implementation that only keeps a reference to the error text and the error (if any), not to the
45      * message parameters, in order to avoid memory leaks. This addresses LOG4J2-1368.
46      * @since 2.6
47      */

48     static class StatusMessage implements Message {
49         private static final long serialVersionUID = 4199272162767841280L;
50         private final String formattedMessage;
51         private final Throwable throwable;
52
53         public StatusMessage(final String formattedMessage, final Throwable throwable) {
54             this.formattedMessage = formattedMessage;
55             this.throwable = throwable;
56         }
57
58         @Override
59         public String getFormattedMessage() {
60             return formattedMessage;
61         }
62
63         @Override
64         public String getFormat() {
65             return formattedMessage;
66         }
67
68         @Override
69         public Object[] getParameters() {
70             return null;
71         }
72
73         @Override
74         public Throwable getThrowable() {
75             return throwable;
76         }
77     }
78
79     /**
80      * Constructs a message factory with default flow strings.
81      */

82     public ParameterizedNoReferenceMessageFactory() {
83     }
84
85     /**
86      * Instance of ParameterizedStatusMessageFactory.
87      */

88     public static final ParameterizedNoReferenceMessageFactory INSTANCE = new ParameterizedNoReferenceMessageFactory();
89
90     /**
91      * Creates {@link SimpleMessage} instances containing the formatted parameterized message string.
92      *
93      * @param message The message pattern.
94      * @param params The message parameters.
95      * @return The Message.
96      *
97      * @see MessageFactory#newMessage(String, Object...)
98      */

99     @Override
100     public Message newMessage(final String message, final Object... params) {
101         if (params == null) {
102             return new SimpleMessage(message);
103         }
104         final ParameterizedMessage msg = new ParameterizedMessage(message, params);
105         return new StatusMessage(msg.getFormattedMessage(), msg.getThrowable());
106     }
107 }
108