001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.log4j.builders.layout; 018 019import org.apache.log4j.Layout; 020import org.apache.log4j.bridge.LayoutWrapper; 021import org.apache.log4j.builders.AbstractBuilder; 022import org.apache.log4j.config.Log4j1Configuration; 023import org.apache.log4j.config.PropertiesConfiguration; 024import org.apache.log4j.xml.XmlConfiguration; 025import org.apache.logging.log4j.Logger; 026import org.apache.logging.log4j.core.config.plugins.Plugin; 027import org.apache.logging.log4j.core.config.plugins.PluginAliases; 028import org.apache.logging.log4j.core.layout.PatternLayout; 029import org.apache.logging.log4j.status.StatusLogger; 030import org.w3c.dom.Element; 031import org.w3c.dom.Node; 032import org.w3c.dom.NodeList; 033 034import java.util.Properties; 035 036import static org.apache.log4j.builders.BuilderManager.CATEGORY; 037import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG; 038 039/** 040 * Build a Pattern Layout 041 */ 042@Plugin(name = "org.apache.log4j.PatternLayout", category = CATEGORY) 043@PluginAliases("org.apache.log4j.EnhancedPatternLayout") 044public class PatternLayoutBuilder extends AbstractBuilder implements LayoutBuilder { 045 046 private static final Logger LOGGER = StatusLogger.getLogger(); 047 private static final String PATTERN = "ConversionPattern"; 048 049 public PatternLayoutBuilder() { 050 } 051 052 public PatternLayoutBuilder(String prefix, Properties props) { 053 super(prefix, props); 054 } 055 056 @Override 057 public Layout parseLayout(final Element layoutElement, final XmlConfiguration config) { 058 NodeList params = layoutElement.getElementsByTagName("param"); 059 final int length = params.getLength(); 060 String pattern = null; 061 for (int index = 0; index < length; ++ index) { 062 Node currentNode = params.item(index); 063 if (currentNode.getNodeType() == Node.ELEMENT_NODE) { 064 Element currentElement = (Element) currentNode; 065 if (currentElement.getTagName().equals(PARAM_TAG)) { 066 if (PATTERN.equalsIgnoreCase(currentElement.getAttribute("name"))) { 067 pattern = currentElement.getAttribute("value"); 068 break; 069 } 070 } 071 } 072 } 073 return createLayout(pattern, config); 074 } 075 076 @Override 077 public Layout parseLayout(final PropertiesConfiguration config) { 078 String pattern = getProperty(PATTERN); 079 return createLayout(pattern, config); 080 } 081 082 private Layout createLayout(String pattern, final Log4j1Configuration config) { 083 if (pattern == null) { 084 LOGGER.info("No pattern provided for pattern layout, using default pattern"); 085 pattern = PatternLayout.DEFAULT_CONVERSION_PATTERN; 086 } 087 return new LayoutWrapper(PatternLayout.newBuilder() 088 .withPattern(pattern 089 // Log4j 2's %x (NDC) is not compatible with Log4j 1's 090 // %x 091 // Log4j 1: "foo bar baz" 092 // Log4j 2: "[foo, bar, baz]" 093 // Use %ndc to get the Log4j 1 format 094 .replace("%x", "%ndc") 095 096 // Log4j 2's %X (MDC) is not compatible with Log4j 1's 097 // %X 098 // Log4j 1: "{{foo,bar}{hoo,boo}}" 099 // Log4j 2: "{foo=bar,hoo=boo}" 100 // Use %properties to get the Log4j 1 format 101 .replace("%X", "%properties")) 102 .withConfiguration(config) 103 .build()); 104 } 105}