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