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