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