View Javadoc

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 java.io.IOException;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.text.MessageFormat;
23  import java.util.Arrays;
24  import java.util.IllegalFormatException;
25  
26  import org.apache.logging.log4j.Logger;
27  import org.apache.logging.log4j.status.StatusLogger;
28  
29  /**
30   * Handles messages that consist of a format string conforming to java.text.MessageFormat.
31   */
32  public class MessageFormatMessage implements Message {
33  
34      private static final Logger LOGGER = StatusLogger.getLogger();
35  
36      private static final long serialVersionUID = -665975803997290697L;
37  
38      private static final int HASHVAL = 31;
39  
40      private String messagePattern;
41      private transient Object[] argArray;
42      private String[] stringArgs;
43      private transient String formattedMessage;
44      private transient Throwable throwable;
45  
46      public MessageFormatMessage(final String messagePattern, final Object... arguments) {
47          this.messagePattern = messagePattern;
48          this.argArray = arguments;
49          if (arguments != null && arguments.length > 0 && arguments[arguments.length - 1] instanceof Throwable) {
50              this.throwable = (Throwable) arguments[arguments.length - 1];
51          }
52      }
53  
54      /**
55       * Returns the formatted message.
56       * @return the formatted message.
57       */
58      @Override
59      public String getFormattedMessage() {
60          if (formattedMessage == null) {
61              formattedMessage = formatMessage(messagePattern, argArray);
62          }
63          return formattedMessage;
64      }
65  
66      /**
67       * Returns the message pattern.
68       * @return the message pattern.
69       */
70      @Override
71      public String getFormat() {
72          return messagePattern;
73      }
74  
75      /**
76       * Returns the message parameters.
77       * @return the message parameters.
78       */
79      @Override
80      public Object[] getParameters() {
81          if (argArray != null) {
82              return argArray;
83          }
84          return stringArgs;
85      }
86  
87      protected String formatMessage(final String msgPattern, final Object... args) {
88          try {
89              return MessageFormat.format(msgPattern, args);
90          } catch (final IllegalFormatException ife) {
91              LOGGER.error("Unable to format msg: " + msgPattern, ife);
92              return msgPattern;
93          }
94      }
95  
96      @Override
97      public boolean equals(final Object o) {
98          if (this == o) {
99              return true;
100         }
101         if (o == null || getClass() != o.getClass()) {
102             return false;
103         }
104 
105         final MessageFormatMessage that = (MessageFormatMessage) o;
106 
107         if (messagePattern != null ? !messagePattern.equals(that.messagePattern) : that.messagePattern != null) {
108             return false;
109         }
110         if (!Arrays.equals(stringArgs, that.stringArgs)) {
111             return false;
112         }
113 
114         return true;
115     }
116 
117     @Override
118     public int hashCode() {
119         int result = messagePattern != null ? messagePattern.hashCode() : 0;
120         result = HASHVAL * result + (stringArgs != null ? Arrays.hashCode(stringArgs) : 0);
121         return result;
122     }
123 
124 
125     @Override
126     public String toString() {
127         return "StringFormatMessage[messagePattern=" + messagePattern + ", args=" +
128             Arrays.toString(argArray) + ']';
129     }
130 
131     private void writeObject(final ObjectOutputStream out) throws IOException {
132         out.defaultWriteObject();
133         getFormattedMessage();
134         out.writeUTF(formattedMessage);
135         out.writeUTF(messagePattern);
136         out.writeInt(argArray.length);
137         stringArgs = new String[argArray.length];
138         int i = 0;
139         for (final Object obj : argArray) {
140             stringArgs[i] = obj.toString();
141             ++i;
142         }
143     }
144 
145     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
146         in.defaultReadObject();
147         formattedMessage = in.readUTF();
148         messagePattern = in.readUTF();
149         final int length = in.readInt();
150         stringArgs = new String[length];
151         for (int i = 0; i < length; ++i) {
152             stringArgs[i] = in.readUTF();
153         }
154     }
155 
156     /**
157      * Return the throwable passed to the Message.
158      *
159      * @return the Throwable.
160      */
161     @Override
162     public Throwable getThrowable() {
163         return throwable;
164     }
165 }