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