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.core.layout;
18  
19  import java.io.Serializable;
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import org.apache.logging.log4j.Logger;
24  import org.apache.logging.log4j.core.Layout;
25  import org.apache.logging.log4j.core.LogEvent;
26  import org.apache.logging.log4j.core.config.Configuration;
27  import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
28  import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
29  import org.apache.logging.log4j.status.StatusLogger;
30  
31  /**
32   * Abstract base class for Layouts.
33   *
34   * @param <T>
35   *            The Class that the Layout will format the LogEvent into.
36   */
37  public abstract class AbstractLayout<T extends Serializable> implements Layout<T> {
38  
39      /**
40       * Subclasses can extend this abstract Builder.
41       *
42       * @param <B> The type to build.
43       */
44      public abstract static class Builder<B extends Builder<B>> {
45  
46          @PluginConfiguration
47          private Configuration configuration;
48  
49          @PluginBuilderAttribute
50          private byte[] footer;
51  
52          @PluginBuilderAttribute
53          private byte[] header;
54  
55          @SuppressWarnings("unchecked")
56          public B asBuilder() {
57              return (B) this;
58          }
59  
60          public Configuration getConfiguration() {
61              return configuration;
62          }
63  
64          public byte[] getFooter() {
65              return footer;
66          }
67  
68          public byte[] getHeader() {
69              return header;
70          }
71  
72          public B setConfiguration(final Configuration configuration) {
73              this.configuration = configuration;
74              return asBuilder();
75          }
76  
77          public B setFooter(final byte[] footer) {
78              this.footer = footer;
79              return asBuilder();
80          }
81  
82          public B setHeader(final byte[] header) {
83              this.header = header;
84              return asBuilder();
85          }
86  
87      }
88  
89      /**
90       * Allow subclasses access to the status logger without creating another instance.
91       */
92      protected static final Logger LOGGER = StatusLogger.getLogger();
93  
94      /**
95       * The current Configuration.
96       */
97      protected final Configuration configuration;
98  
99      /**
100      * The number of events successfully processed by this layout.
101      */
102     protected long eventCount;
103 
104     /**
105      * The footer to add when the stream is closed. May be null.
106      */
107     protected final byte[] footer;
108 
109     /**
110      * The header to include when the stream is opened. May be null.
111      */
112     protected final byte[] header;
113 
114     /**
115      * Constructs a layout with an optional header and footer.
116      *
117      * @param header
118      *            The header to include when the stream is opened. May be null.
119      * @param footer
120      *            The footer to add when the stream is closed. May be null.
121      * @deprecated Use {@link #AbstractLayout(Configuration, byte[], byte[])}
122      */
123     @Deprecated
124     public AbstractLayout(final byte[] header, final byte[] footer) {
125         this(null, header, footer);
126     }
127 
128     /**
129      * Constructs a layout with an optional header and footer.
130      *
131      * @param configuration
132      *            The configuration
133      * @param header
134      *            The header to include when the stream is opened. May be null.
135      * @param footer
136      *            The footer to add when the stream is closed. May be null.
137      */
138     public AbstractLayout(final Configuration configuration, final byte[] header, final byte[] footer) {
139         super();
140         this.configuration = configuration;
141         this.header = header;
142         this.footer = footer;
143     }
144 
145     public Configuration getConfiguration() {
146         return configuration;
147     }
148 
149     @Override
150     public Map<String, String> getContentFormat() {
151         return new HashMap<>();
152     }
153 
154     /**
155      * Returns the footer, if one is available.
156      *
157      * @return A byte array containing the footer.
158      */
159     @Override
160     public byte[] getFooter() {
161         return footer;
162     }
163 
164     /**
165      * Returns the header, if one is available.
166      *
167      * @return A byte array containing the header.
168      */
169     @Override
170     public byte[] getHeader() {
171         return header;
172     }
173 
174     protected void markEvent() {
175         eventCount++;
176     }
177 
178     /**
179      * Encodes the specified source LogEvent to some binary representation and writes the result to the specified
180      * destination.
181      * <p>
182      * The default implementation of this method delegates to the {@link #toByteArray(LogEvent)} method which allocates
183      * temporary objects.
184      * </p><p>
185      * Subclasses can override this method to provide a garbage-free implementation. For text-based layouts,
186      * {@code AbstractStringLayout} provides various convenience methods to help with this:
187      * </p>
188      * <pre>@Plugin(name = "MyLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
189      * public final class MyLayout extends AbstractStringLayout {
190      *     @Override
191      *     public void encode(LogEvent event, ByteBufferDestination destination) {
192      *         StringBuilder text = getStringBuilder();
193      *         convertLogEventToText(event, text);
194      *         getStringBuilderEncoder().encode(text, destination);
195      *     }
196      *
197      *     private void convertLogEventToText(LogEvent event, StringBuilder destination) {
198      *         ... // append a text representation of the log event to the StringBuilder
199      *     }
200      * }
201      * </pre>
202      *
203      * @param event the LogEvent to encode.
204      * @param destination holds the ByteBuffer to write into.
205      * @see AbstractStringLayout#getStringBuilder()
206      * @see AbstractStringLayout#getStringBuilderEncoder()
207      */
208     @Override
209     public void encode(final LogEvent event, final ByteBufferDestination destination) {
210         final byte[] data = toByteArray(event);
211         destination.writeBytes(data, 0, data.length);
212     }
213 }