1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.message;
18
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.status.StatusLogger;
21
22 import java.io.IOException;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.text.Format;
26 import java.text.MessageFormat;
27 import java.util.Arrays;
28 import java.util.regex.Pattern;
29
30
31
32
33
34 public class FormattedMessage implements Message {
35
36 private static final Logger LOGGER = StatusLogger.getLogger();
37
38 private static final long serialVersionUID = -665975803997290697L;
39
40 private static final int HASHVAL = 31;
41
42 private static final String FORMAT_SPECIFIER = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
43
44 private static final Pattern MSG_PATTERN = Pattern.compile(FORMAT_SPECIFIER);
45
46 private String messagePattern;
47 private transient Object[] argArray;
48 private String[] stringArgs;
49 private transient String formattedMessage;
50 private final Throwable throwable;
51
52 private Message message;
53
54 public FormattedMessage(final String messagePattern, final Object[] arguments, final Throwable throwable) {
55 this.messagePattern = messagePattern;
56 this.argArray = arguments;
57 this.throwable = throwable;
58 }
59
60 public FormattedMessage(final String messagePattern, final Object[] arguments) {
61 this.messagePattern = messagePattern;
62 this.argArray = arguments;
63 this.throwable = null;
64 }
65
66
67
68
69
70
71 public FormattedMessage(final String messagePattern, final Object arg) {
72 this.messagePattern = messagePattern;
73 this.argArray = new Object[] {arg};
74 this.throwable = null;
75 }
76
77
78
79
80
81
82
83 public FormattedMessage(final String messagePattern, final Object arg1, final Object arg2) {
84 this(messagePattern, new Object[]{arg1, arg2});
85 }
86
87
88
89
90
91
92 @Override
93 public String getFormattedMessage() {
94 if (formattedMessage == null) {
95 if (message == null) {
96 message = getMessage(messagePattern, argArray, throwable);
97 }
98 formattedMessage = message.getFormattedMessage();
99 }
100 return formattedMessage;
101 }
102
103
104
105
106
107 @Override
108 public String getFormat() {
109 return messagePattern;
110 }
111
112
113
114
115
116 @Override
117 public Object[] getParameters() {
118 if (argArray != null) {
119 return argArray;
120 }
121 return stringArgs;
122 }
123
124 protected Message getMessage(final String msgPattern, final Object[] args, final Throwable throwable) {
125 try {
126 final MessageFormat format = new MessageFormat(msgPattern);
127 final Format[] formats = format.getFormats();
128 if (formats != null && formats.length > 0) {
129 return new MessageFormatMessage(msgPattern, args);
130 }
131 } catch (final Exception ex) {
132
133 }
134 try {
135 if (MSG_PATTERN.matcher(msgPattern).find()) {
136 return new StringFormattedMessage(msgPattern, args);
137 }
138 } catch (final Exception ex) {
139
140 }
141 return new ParameterizedMessage(msgPattern, args, throwable);
142 }
143
144 @Override
145 public boolean equals(final Object o) {
146 if (this == o) {
147 return true;
148 }
149 if (o == null || getClass() != o.getClass()) {
150 return false;
151 }
152
153 final FormattedMessage that = (FormattedMessage) o;
154
155 if (messagePattern != null ? !messagePattern.equals(that.messagePattern) : that.messagePattern != null) {
156 return false;
157 }
158 if (!Arrays.equals(stringArgs, that.stringArgs)) {
159 return false;
160 }
161
162 return true;
163 }
164
165 @Override
166 public int hashCode() {
167 int result = messagePattern != null ? messagePattern.hashCode() : 0;
168 result = HASHVAL * result + (stringArgs != null ? Arrays.hashCode(stringArgs) : 0);
169 return result;
170 }
171
172
173 @Override
174 public String toString() {
175 return "FormattedMessage[messagePattern=" + messagePattern + ", args=" +
176 Arrays.toString(argArray) + "]";
177 }
178
179 private void writeObject(final ObjectOutputStream out) throws IOException {
180 out.defaultWriteObject();
181 getFormattedMessage();
182 out.writeUTF(formattedMessage);
183 out.writeUTF(messagePattern);
184 out.writeInt(argArray.length);
185 stringArgs = new String[argArray.length];
186 int i = 0;
187 for (final Object obj : argArray) {
188 stringArgs[i] = obj.toString();
189 ++i;
190 }
191 }
192
193 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
194 in.defaultReadObject();
195 formattedMessage = in.readUTF();
196 messagePattern = in.readUTF();
197 final int length = in.readInt();
198 stringArgs = new String[length];
199 for (int i = 0; i < length; ++i) {
200 stringArgs[i] = in.readUTF();
201 }
202 }
203
204
205
206
207
208
209 @Override
210 public Throwable getThrowable() {
211 if (throwable != null) {
212 return throwable;
213 }
214 if (message == null) {
215 message = getMessage(messagePattern, argArray, throwable);
216 }
217 return message.getThrowable();
218 }
219 }