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 javax.xml.stream.XMLOutputFactory;
20  import javax.xml.stream.XMLStreamException;
21  import javax.xml.stream.XMLStreamWriter;
22  import java.io.ByteArrayOutputStream;
23  import java.io.Serializable;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.Map;
27  import java.util.SortedMap;
28  import java.util.TreeMap;
29  
30  /**
31   * Represents a Message that consists of a Map.
32   */
33  public class MapMessage implements FormattedMessage, Serializable {
34      /**
35       * When set as the format specifier causes the Map to be formatted as XML.
36       */
37      public static final String XML = "XML";
38      private static final long serialVersionUID = -5031471831131487120L;
39  
40      private final Map<String, String> data;
41  
42      private String format = null;
43  
44      /**
45       * Constructor.
46       */
47      public MapMessage() {
48          data = new HashMap<String, String>();
49      }
50  
51      /**
52       * Constructor based on an existing Map.
53       * @param map The Map.
54       */
55      public MapMessage(Map<String, String> map) {
56          this.data = map;
57      }
58  
59      /**
60       * The format String. Specifying "xml" will cause the message to be XML.
61       * @param format The message format.
62       */
63      public void setFormat(String format) {
64          this.format = format;
65      }
66  
67      /**
68       * Return the format String.
69       * @return the format String.
70       */
71      public String getFormat() {
72          return this.format;
73      }
74  
75  
76      /**
77       * Return the data elements as if they were parameters on the logging event.
78       * @return the data elements.
79       */
80      public Object[] getParameters() {
81          return data.values().toArray();
82      }
83  
84      /**
85       * Return the message.
86       * @return the message.
87       */
88      public String getMessageFormat() {
89          return "";
90      }
91  
92      /**
93       * Return the message data as an unmodifiable Map.
94       * @return the message data as an unmodifiable map.
95       */
96      public Map<String, String> getData() {
97          return Collections.unmodifiableMap(data);
98      }
99  
100     /**
101      * Clear the data.
102      */
103     public void clear() {
104         data.clear();
105     }
106 
107     /**
108      * Add an item to the data Map.
109      * @param key The name of the data item.
110      * @param value The value of the data item.
111      */
112     public void put(String key, String value) {
113         if (value == null) {
114             throw new IllegalArgumentException("No value provided for key " + key);
115         }
116         validate(key, value);
117         data.put(key, value);
118     }
119 
120     protected void validate(String key, String value) {
121 
122     }
123 
124     /**
125      * Add all the elements from the specified Map.
126      * @param map The Map to add.
127      */
128     public void putAll(Map<String, String> map) {
129         data.putAll(map);
130     }
131 
132     /**
133      * Retrieve the value of the element with the specified key or null if the key is not present.
134      * @param key The name of the element.
135      * @return The value of the element or null if the key is not present.
136      */
137     public String get(String key) {
138         return data.get(key);
139     }
140 
141     /**
142      * Remove the element with the specified name.
143      * @param key The name of the element.
144      * @return The previous value of the element.
145      */
146     public String remove(String key) {
147         return data.remove(key);
148     }
149 
150     /**
151      * Format the Structured data as described in RFC 5424.
152      *
153      * @return The formatted String.
154      */
155     public String asString() {
156         return asString(format == null ? "" : format);
157     }
158 
159     /**
160      * Format the Structured data as described in RFC 5424.
161      *
162      * @param format The format identifier. Ignored in this implementation.
163      * @return The formatted String.
164      */
165     public String asString(String format) {
166         StringBuilder sb = new StringBuilder();
167         if (format.equalsIgnoreCase(XML)) {
168             asXML(sb);
169         } else {
170             appendMap(sb);
171         }
172         return sb.toString();
173     }
174 
175     public void asXML(StringBuilder sb) {
176         sb.append("<Map>\n");
177         SortedMap<String, String> sorted = new TreeMap<String, String>(data);
178         for (Map.Entry<String, String> entry : sorted.entrySet()) {
179             sb.append("  <Entry key=").append(entry.getKey()).append(">").append(entry.getValue()).append("</Entry>\n");
180         }
181         sb.append("</Map>");
182     }
183 
184     /**
185      * Format the message and return it.
186      * @return the formatted message.
187      */
188     public String getFormattedMessage() {
189         return asString();
190     }
191 
192     protected void appendMap(StringBuilder sb) {
193         SortedMap<String, String> sorted = new TreeMap<String, String>(data);
194         boolean first = true;
195         for (Map.Entry<String, String> entry : sorted.entrySet()) {
196             if (!first) {
197                 sb.append(" ");
198             }
199             first = false;
200             sb.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
201         }
202     }
203 
204     public MapMessage newInstance(Map<String, String> map) {
205         return new MapMessage(map);
206     }
207 
208     public String toString() {
209         return asString();
210     }
211 
212     public boolean equals(Object o) {
213         if (this == o) {
214             return true;
215         }
216         if (o == null || getClass() != o.getClass()) {
217             return false;
218         }
219 
220         MapMessage that = (MapMessage) o;
221 
222         return this.data.equals(that.data);
223     }
224 
225     public int hashCode() {
226         return data.hashCode();
227     }
228 }