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.io.Serializable;
23  
24  import org.apache.logging.log4j.util.StringBuilderFormattable;
25  import org.apache.logging.log4j.util.StringBuilders;
26  
27  /**
28   * Handles messages that contain an Object.
29   */
30  public class ObjectMessage implements Message, StringBuilderFormattable {
31  
32      private static final long serialVersionUID = -5903272448334166185L;
33  
34      private transient Object obj;
35      private transient String objectString;
36  
37      /**
38       * Creates the ObjectMessage.
39       *
40       * @param obj The Object to format.
41       */
42      public ObjectMessage(final Object obj) {
43          this.obj = obj == null ? "null" : obj;
44      }
45  
46      /**
47       * Returns the formatted object message.
48       *
49       * @return the formatted object message.
50       */
51      @Override
52      public String getFormattedMessage() {
53          // LOG4J2-763: cache formatted string in case obj changes later
54          if (objectString == null) {
55              objectString = String.valueOf(obj);
56          }
57          return objectString;
58      }
59  
60      @Override
61      public void formatTo(final StringBuilder buffer) {
62          if (objectString != null) { //
63              buffer.append(objectString);
64          } else {
65              StringBuilders.appendValue(buffer, obj);
66          }
67      }
68  
69      /**
70       * Returns the object formatted using its toString method.
71       *
72       * @return the String representation of the object.
73       */
74      @Override
75      public String getFormat() {
76          return getFormattedMessage();
77      }
78  
79      /**
80       * Returns the object parameter.
81       *
82       * @return The object.
83       * @since 2.7
84       */
85      public Object getParameter() {
86          return obj;
87      }
88  
89      /**
90       * Returns the object as if it were a parameter.
91       *
92       * @return The object.
93       */
94      @Override
95      public Object[] getParameters() {
96          return new Object[] {obj};
97      }
98  
99      @Override
100     public boolean equals(final Object o) {
101         if (this == o) {
102             return true;
103         }
104         if (o == null || getClass() != o.getClass()) {
105             return false;
106         }
107 
108         final ObjectMessage that = (ObjectMessage) o;
109         return obj == null ? that.obj == null : equalObjectsOrStrings(obj, that.obj);
110     }
111 
112     private boolean equalObjectsOrStrings(final Object left, final Object right) {
113         return left.equals(right) || String.valueOf(left).equals(String.valueOf(right));
114     }
115 
116     @Override
117     public int hashCode() {
118         return obj != null ? obj.hashCode() : 0;
119     }
120 
121     @Override
122     public String toString() {
123         return getFormattedMessage();
124     }
125 
126     private void writeObject(final ObjectOutputStream out) throws IOException {
127         out.defaultWriteObject();
128         if (obj instanceof Serializable) {
129             out.writeObject(obj);
130         } else {
131             out.writeObject(String.valueOf(obj));
132         }
133     }
134 
135     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
136         in.defaultReadObject();
137         obj = in.readObject();
138     }
139 
140     /**
141      * Gets the message if it is a throwable.
142      *
143      * @return the message if it is a throwable.
144      */
145     @Override
146     public Throwable getThrowable() {
147         return obj instanceof Throwable ? (Throwable) obj : null;
148     }
149 }