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.nio.charset.Charset;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.apache.logging.log4j.core.Layout;
24 import org.apache.logging.log4j.core.config.Node;
25 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
27 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
28 import org.apache.logging.log4j.core.jackson.XmlConstants;
29 import org.apache.logging.log4j.core.util.Constants;
30
31 /**
32 * Appends a series of {@code event} elements as defined in the <a href="log4j.dtd">log4j.dtd</a>.
33 *
34 * <h3>Complete well-formed XML vs. fragment XML</h3>
35 * <p>
36 * If you configure {@code complete="true"}, the appender outputs a well-formed XML document where the default namespace is the log4j
37 * namespace {@value XmlConstants#XML_NAMESPACE}. By default, with {@code complete="false"}, you should include the output as an
38 * <em>external entity</em> in a separate file to form a well-formed XML document.
39 * </p>
40 * <p>
41 * A well-formed XML document follows this pattern:
42 * </p>
43 * <pre>
44 <Event xmlns="http://logging.apache.org/log4j/2.0/events" timeMillis="1" thread="MyThreadName" level="DEBUG" loggerName="a.B" loggerFQCN="f.q.c.n" endOfBatch="false">
45 <Marker name="Marker1">
46 <Parents>
47 <Parents name="ParentMarker1">
48 <Parents>
49 <Parents name="GrandMotherMarker"/>
50 <Parents name="GrandFatherMarker"/>
51 </Parents>
52 </Parents>
53 <Parents name="GrandFatherMarker"/>
54 </Parents>
55 </Marker>
56 <Message>Msg</Message>
57 <ContextMap>
58 <item key="MDC.B" value="B_Value"/>
59 <item key="MDC.A" value="A_Value"/>
60 </ContextMap>
61 <ContextStack>
62 <ContextStack>stack_msg1</ContextStack>
63 <ContextStack>stack_msg2</ContextStack>
64 </ContextStack>
65 <Source class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="54"/>
66 <Thrown commonElementCount="0" localizedMessage="testIOEx" message="testIOEx" name="java.io.IOException">
67 <Cause commonElementCount="27" localizedMessage="testNPEx" message="testNPEx" name="java.lang.NullPointerException">
68 <ExtendedStackTrace>
69 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="53" exact="false" location="test-classes/" version="?"/>
70 </ExtendedStackTrace>
71 </Cause>
72 <ExtendedStackTrace>
73 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="56" exact="true" location="test-classes/" version="?"/>
74 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testAllFeatures" file="XmlLayoutTest.java" line="122" exact="true" location="test-classes/" version="?"/>
75 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testLocationOnCompactOnMdcOn" file="XmlLayoutTest.java" line="270" exact="true" location="test-classes/" version="?"/>
76 <ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
77 <ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
78 <ExtendedStackTrace class="sun.reflect.DelegatingMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
79 <ExtendedStackTrace class="java.lang.reflect.Method" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
80 <ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod$1" method="runReflectiveCall" file="FrameworkMethod.java" line="47" exact="true" location="junit-4.11.jar" version="?"/>
81 <ExtendedStackTrace class="org.junit.internal.runners.model.ReflectiveCallable" method="run" file="ReflectiveCallable.java" line="12" exact="true" location="junit-4.11.jar" version="?"/>
82 <ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod" method="invokeExplosively" file="FrameworkMethod.java" line="44" exact="true" location="junit-4.11.jar" version="?"/>
83 <ExtendedStackTrace class="org.junit.internal.runners.statements.InvokeMethod" method="evaluate" file="InvokeMethod.java" line="17" exact="true" location="junit-4.11.jar" version="?"/>
84 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runLeaf" file="ParentRunner.java" line="271" exact="true" location="junit-4.11.jar" version="?"/>
85 <ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="70" exact="true" location="junit-4.11.jar" version="?"/>
86 <ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="50" exact="true" location="junit-4.11.jar" version="?"/>
87 <ExtendedStackTrace class="org.junit.runners.ParentRunner$3" method="run" file="ParentRunner.java" line="238" exact="true" location="junit-4.11.jar" version="?"/>
88 <ExtendedStackTrace class="org.junit.runners.ParentRunner$1" method="schedule" file="ParentRunner.java" line="63" exact="true" location="junit-4.11.jar" version="?"/>
89 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runChildren" file="ParentRunner.java" line="236" exact="true" location="junit-4.11.jar" version="?"/>
90 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="access$000" file="ParentRunner.java" line="53" exact="true" location="junit-4.11.jar" version="?"/>
91 <ExtendedStackTrace class="org.junit.runners.ParentRunner$2" method="evaluate" file="ParentRunner.java" line="229" exact="true" location="junit-4.11.jar" version="?"/>
92 <ExtendedStackTrace class="org.junit.internal.runners.statements.RunBefores" method="evaluate" file="RunBefores.java" line="26" exact="true" location="junit-4.11.jar" version="?"/>
93 <ExtendedStackTrace class="org.junit.internal.runners.statements.RunAfters" method="evaluate" file="RunAfters.java" line="27" exact="true" location="junit-4.11.jar" version="?"/>
94 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="run" file="ParentRunner.java" line="309" exact="true" location="junit-4.11.jar" version="?"/>
95 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference" method="run" file="JUnit4TestReference.java" line="50" exact="true" location=".cp/" version="?"/>
96 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.TestExecution" method="run" file="TestExecution.java" line="38" exact="true" location=".cp/" version="?"/>
97 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="467" exact="true" location=".cp/" version="?"/>
98 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="683" exact="true" location=".cp/" version="?"/>
99 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="run" file="RemoteTestRunner.java" line="390" exact="true" location=".cp/" version="?"/>
100 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="main" file="RemoteTestRunner.java" line="197" exact="true" location=".cp/" version="?"/>
101 </ExtendedStackTrace>
102 <Suppressed>
103 <Suppressed commonElementCount="0" localizedMessage="I am suppressed exception 1" message="I am suppressed exception 1" name="java.lang.IndexOutOfBoundsException">
104 <ExtendedStackTrace>
105 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="57" exact="true" location="test-classes/" version="?"/>
106 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testAllFeatures" file="XmlLayoutTest.java" line="122" exact="true" location="test-classes/" version="?"/>
107 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testLocationOnCompactOnMdcOn" file="XmlLayoutTest.java" line="270" exact="true" location="test-classes/" version="?"/>
108 <ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
109 <ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
110 <ExtendedStackTrace class="sun.reflect.DelegatingMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
111 <ExtendedStackTrace class="java.lang.reflect.Method" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
112 <ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod$1" method="runReflectiveCall" file="FrameworkMethod.java" line="47" exact="true" location="junit-4.11.jar" version="?"/>
113 <ExtendedStackTrace class="org.junit.internal.runners.model.ReflectiveCallable" method="run" file="ReflectiveCallable.java" line="12" exact="true" location="junit-4.11.jar" version="?"/>
114 <ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod" method="invokeExplosively" file="FrameworkMethod.java" line="44" exact="true" location="junit-4.11.jar" version="?"/>
115 <ExtendedStackTrace class="org.junit.internal.runners.statements.InvokeMethod" method="evaluate" file="InvokeMethod.java" line="17" exact="true" location="junit-4.11.jar" version="?"/>
116 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runLeaf" file="ParentRunner.java" line="271" exact="true" location="junit-4.11.jar" version="?"/>
117 <ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="70" exact="true" location="junit-4.11.jar" version="?"/>
118 <ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="50" exact="true" location="junit-4.11.jar" version="?"/>
119 <ExtendedStackTrace class="org.junit.runners.ParentRunner$3" method="run" file="ParentRunner.java" line="238" exact="true" location="junit-4.11.jar" version="?"/>
120 <ExtendedStackTrace class="org.junit.runners.ParentRunner$1" method="schedule" file="ParentRunner.java" line="63" exact="true" location="junit-4.11.jar" version="?"/>
121 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runChildren" file="ParentRunner.java" line="236" exact="true" location="junit-4.11.jar" version="?"/>
122 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="access$000" file="ParentRunner.java" line="53" exact="true" location="junit-4.11.jar" version="?"/>
123 <ExtendedStackTrace class="org.junit.runners.ParentRunner$2" method="evaluate" file="ParentRunner.java" line="229" exact="true" location="junit-4.11.jar" version="?"/>
124 <ExtendedStackTrace class="org.junit.internal.runners.statements.RunBefores" method="evaluate" file="RunBefores.java" line="26" exact="true" location="junit-4.11.jar" version="?"/>
125 <ExtendedStackTrace class="org.junit.internal.runners.statements.RunAfters" method="evaluate" file="RunAfters.java" line="27" exact="true" location="junit-4.11.jar" version="?"/>
126 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="run" file="ParentRunner.java" line="309" exact="true" location="junit-4.11.jar" version="?"/>
127 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference" method="run" file="JUnit4TestReference.java" line="50" exact="true" location=".cp/" version="?"/>
128 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.TestExecution" method="run" file="TestExecution.java" line="38" exact="true" location=".cp/" version="?"/>
129 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="467" exact="true" location=".cp/" version="?"/>
130 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="683" exact="true" location=".cp/" version="?"/>
131 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="run" file="RemoteTestRunner.java" line="390" exact="true" location=".cp/" version="?"/>
132 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="main" file="RemoteTestRunner.java" line="197" exact="true" location=".cp/" version="?"/>
133 </ExtendedStackTrace>
134 </Suppressed>
135 <Suppressed commonElementCount="0" localizedMessage="I am suppressed exception 2" message="I am suppressed exception 2" name="java.lang.IndexOutOfBoundsException">
136 <ExtendedStackTrace>
137 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.LogEventFixtures" method="createLogEvent" file="LogEventFixtures.java" line="58" exact="true" location="test-classes/" version="?"/>
138 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testAllFeatures" file="XmlLayoutTest.java" line="122" exact="true" location="test-classes/" version="?"/>
139 <ExtendedStackTrace class="org.apache.logging.log4j.core.layout.XmlLayoutTest" method="testLocationOnCompactOnMdcOn" file="XmlLayoutTest.java" line="270" exact="true" location="test-classes/" version="?"/>
140 <ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
141 <ExtendedStackTrace class="sun.reflect.NativeMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
142 <ExtendedStackTrace class="sun.reflect.DelegatingMethodAccessorImpl" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
143 <ExtendedStackTrace class="java.lang.reflect.Method" method="invoke" line="-1" exact="false" location="?" version="1.7.0_55"/>
144 <ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod$1" method="runReflectiveCall" file="FrameworkMethod.java" line="47" exact="true" location="junit-4.11.jar" version="?"/>
145 <ExtendedStackTrace class="org.junit.internal.runners.model.ReflectiveCallable" method="run" file="ReflectiveCallable.java" line="12" exact="true" location="junit-4.11.jar" version="?"/>
146 <ExtendedStackTrace class="org.junit.runners.model.FrameworkMethod" method="invokeExplosively" file="FrameworkMethod.java" line="44" exact="true" location="junit-4.11.jar" version="?"/>
147 <ExtendedStackTrace class="org.junit.internal.runners.statements.InvokeMethod" method="evaluate" file="InvokeMethod.java" line="17" exact="true" location="junit-4.11.jar" version="?"/>
148 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runLeaf" file="ParentRunner.java" line="271" exact="true" location="junit-4.11.jar" version="?"/>
149 <ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="70" exact="true" location="junit-4.11.jar" version="?"/>
150 <ExtendedStackTrace class="org.junit.runners.BlockJUnit4ClassRunner" method="runChild" file="BlockJUnit4ClassRunner.java" line="50" exact="true" location="junit-4.11.jar" version="?"/>
151 <ExtendedStackTrace class="org.junit.runners.ParentRunner$3" method="run" file="ParentRunner.java" line="238" exact="true" location="junit-4.11.jar" version="?"/>
152 <ExtendedStackTrace class="org.junit.runners.ParentRunner$1" method="schedule" file="ParentRunner.java" line="63" exact="true" location="junit-4.11.jar" version="?"/>
153 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="runChildren" file="ParentRunner.java" line="236" exact="true" location="junit-4.11.jar" version="?"/>
154 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="access$000" file="ParentRunner.java" line="53" exact="true" location="junit-4.11.jar" version="?"/>
155 <ExtendedStackTrace class="org.junit.runners.ParentRunner$2" method="evaluate" file="ParentRunner.java" line="229" exact="true" location="junit-4.11.jar" version="?"/>
156 <ExtendedStackTrace class="org.junit.internal.runners.statements.RunBefores" method="evaluate" file="RunBefores.java" line="26" exact="true" location="junit-4.11.jar" version="?"/>
157 <ExtendedStackTrace class="org.junit.internal.runners.statements.RunAfters" method="evaluate" file="RunAfters.java" line="27" exact="true" location="junit-4.11.jar" version="?"/>
158 <ExtendedStackTrace class="org.junit.runners.ParentRunner" method="run" file="ParentRunner.java" line="309" exact="true" location="junit-4.11.jar" version="?"/>
159 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference" method="run" file="JUnit4TestReference.java" line="50" exact="true" location=".cp/" version="?"/>
160 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.TestExecution" method="run" file="TestExecution.java" line="38" exact="true" location=".cp/" version="?"/>
161 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="467" exact="true" location=".cp/" version="?"/>
162 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="runTests" file="RemoteTestRunner.java" line="683" exact="true" location=".cp/" version="?"/>
163 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="run" file="RemoteTestRunner.java" line="390" exact="true" location=".cp/" version="?"/>
164 <ExtendedStackTrace class="org.eclipse.jdt.internal.junit.runner.RemoteTestRunner" method="main" file="RemoteTestRunner.java" line="197" exact="true" location=".cp/" version="?"/>
165 </ExtendedStackTrace>
166 </Suppressed>
167 </Suppressed>
168 </Thrown>
169 </Event>
170 </pre>
171 * <p>
172 * If {@code complete="false"}, the appender does not write the XML processing instruction and the root element.
173 * </p>
174 * <p>
175 * This approach enforces the independence of the XmlLayout and the appender where you embed it.
176 * </p>
177 * <h3>Encoding</h3>
178 * <p>
179 * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise events containing non
180 * ASCII characters could result in corrupted log files.
181 * </p>
182 * <h3>Pretty vs. compact XML</h3>
183 * <p>
184 * By default, the XML layout is not compact (compact = not "pretty") with {@code compact="false"}, which means the appender uses
185 * end-of-line characters and indents lines to format the XML. If {@code compact="true"}, then no end-of-line or indentation is used.
186 * Message content may contain, of course, end-of-lines.
187 * </p>
188 */
189 @Plugin(name = "XmlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
190 public final class XmlLayout extends AbstractJacksonLayout {
191
192 private static final long serialVersionUID = 1L;
193
194 private static final String ROOT_TAG = "Events";
195
196 protected XmlLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, final Charset charset) {
197 super(new JacksonFactory.XML().newWriter(locationInfo, properties, compact), charset, compact, complete, false);
198 }
199
200 /**
201 * Returns appropriate XML headers.
202 * <ol>
203 * <li>XML processing instruction</li>
204 * <li>XML root element</li>
205 * </ol>
206 *
207 * @return a byte array containing the header.
208 */
209 @Override
210 public byte[] getHeader() {
211 if (!complete) {
212 return null;
213 }
214 final StringBuilder buf = new StringBuilder();
215 buf.append("<?xml version=\"1.0\" encoding=\"");
216 buf.append(this.getCharset().name());
217 buf.append("\"?>");
218 buf.append(this.eol);
219 // Make the log4j namespace the default namespace, no need to use more space with a namespace prefix.
220 buf.append('<');
221 buf.append(ROOT_TAG);
222 buf.append(" xmlns=\"" + XmlConstants.XML_NAMESPACE + "\">");
223 buf.append(this.eol);
224 return buf.toString().getBytes(this.getCharset());
225 }
226
227 /**
228 * Returns appropriate XML footer.
229 *
230 * @return a byte array containing the footer, closing the XML root element.
231 */
232 @Override
233 public byte[] getFooter() {
234 if (!complete) {
235 return null;
236 }
237 return getBytes("</" + ROOT_TAG + '>' + this.eol);
238 }
239
240 /**
241 * Gets this XmlLayout's content format. Specified by:
242 * <ul>
243 * <li>Key: "dtd" Value: "log4j-events.dtd"</li>
244 * <li>Key: "version" Value: "2.0"</li>
245 * </ul>
246 *
247 * @return Map of content format keys supporting XmlLayout
248 */
249 @Override
250 public Map<String, String> getContentFormat() {
251 final Map<String, String> result = new HashMap<String, String>();
252 // result.put("dtd", "log4j-events.dtd");
253 result.put("xsd", "log4j-events.xsd");
254 result.put("version", "2.0");
255 return result;
256 }
257
258 @Override
259 /**
260 * @return The content type.
261 */
262 public String getContentType() {
263 return "text/xml; charset=" + this.getCharset();
264 }
265
266 /**
267 * Creates an XML Layout.
268 *
269 * @param locationInfo If "true", includes the location information in the generated XML.
270 * @param properties If "true", includes the thread context in the generated XML.
271 * @param complete If "true", includes the XML header and footer, defaults to "false".
272 * @param compact If "true", does not use end-of-lines and indentation, defaults to "false".
273 * @param charset The character set to use, if {@code null}, uses "UTF-8".
274 * @return An XML Layout.
275 */
276 @PluginFactory
277 public static XmlLayout createLayout(
278 // @formatter:off
279 @PluginAttribute(value = "locationInfo", defaultBoolean = false) final boolean locationInfo,
280 @PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties,
281 @PluginAttribute(value = "complete", defaultBoolean = false) final boolean complete,
282 @PluginAttribute(value = "compact", defaultBoolean = false) final boolean compact,
283 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset)
284 // @formatter:on
285 {
286 return new XmlLayout(locationInfo, properties, complete, compact, charset);
287 }
288
289 /**
290 * Creates an XML Layout using the default settings.
291 *
292 * @return an XML Layout.
293 */
294 public static XmlLayout createDefaultLayout() {
295 return new XmlLayout(false, false, false, false, Constants.UTF_8);
296 }
297 }