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 static org.apache.log4j.builders.BuilderManager.CATEGORY; 020import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR; 021import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG; 022import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR; 023import static org.apache.log4j.xml.XmlConfiguration.forEachElement; 024 025import java.util.Properties; 026import java.util.concurrent.atomic.AtomicBoolean; 027import java.util.concurrent.atomic.AtomicReference; 028 029import org.apache.log4j.Layout; 030import org.apache.log4j.bridge.LayoutWrapper; 031import org.apache.log4j.builders.AbstractBuilder; 032import org.apache.log4j.config.Log4j1Configuration; 033import org.apache.log4j.config.PropertiesConfiguration; 034import org.apache.log4j.xml.XmlConfiguration; 035import org.apache.logging.log4j.Logger; 036import org.apache.logging.log4j.core.config.plugins.Plugin; 037import org.apache.logging.log4j.core.layout.PatternLayout; 038import org.apache.logging.log4j.status.StatusLogger; 039import org.w3c.dom.Element; 040 041/** 042 * Build a Pattern Layout 043 */ 044@Plugin(name = "org.apache.log4j.TTCCLayout", category = CATEGORY) 045public class TTCCLayoutBuilder extends AbstractBuilder implements LayoutBuilder { 046 047 private static final Logger LOGGER = StatusLogger.getLogger(); 048 049 private static final String THREAD_PRINTING_PARAM = "ThreadPrinting"; 050 private static final String CATEGORY_PREFIXING_PARAM = "CategoryPrefixing"; 051 private static final String CONTEXT_PRINTING_PARAM = "ContextPrinting"; 052 private static final String DATE_FORMAT_PARAM = "DateFormat"; 053 private static final String TIMEZONE_FORMAT = "TimeZone"; 054 055 public TTCCLayoutBuilder() { 056 } 057 058 public TTCCLayoutBuilder(String prefix, Properties props) { 059 super(prefix, props); 060 } 061 062 @Override 063 public Layout parseLayout(Element layoutElement, XmlConfiguration config) { 064 final AtomicBoolean threadPrinting = new AtomicBoolean(); 065 final AtomicBoolean categoryPrefixing = new AtomicBoolean(); 066 final AtomicBoolean contextPrinting = new AtomicBoolean(); 067 final AtomicReference<String> dateFormat = new AtomicReference<>(); 068 final AtomicReference<String> timezone = new AtomicReference<>(); 069 forEachElement(layoutElement.getElementsByTagName("param"), currentElement -> { 070 if (currentElement.getTagName().equals(PARAM_TAG)) { 071 switch (currentElement.getAttribute(NAME_ATTR)) { 072 case THREAD_PRINTING_PARAM: 073 threadPrinting.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR))); 074 break; 075 case CATEGORY_PREFIXING_PARAM: 076 categoryPrefixing.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR))); 077 break; 078 case CONTEXT_PRINTING_PARAM: 079 contextPrinting.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR))); 080 break; 081 case DATE_FORMAT_PARAM: 082 dateFormat.set(currentElement.getAttribute(VALUE_ATTR)); 083 break; 084 case TIMEZONE_FORMAT: 085 timezone.set(currentElement.getAttribute(VALUE_ATTR)); 086 break; 087 } 088 } 089 }); 090 return createLayout(threadPrinting.get(), categoryPrefixing.get(), contextPrinting.get(), 091 dateFormat.get(), timezone.get(), config); 092 } 093 094 @Override 095 public Layout parseLayout(PropertiesConfiguration config) { 096 boolean threadPrinting = getBooleanProperty(THREAD_PRINTING_PARAM); 097 boolean categoryPrefixing = getBooleanProperty(CATEGORY_PREFIXING_PARAM); 098 boolean contextPrinting = getBooleanProperty(CONTEXT_PRINTING_PARAM); 099 String dateFormat = getProperty(DATE_FORMAT_PARAM); 100 String timezone = getProperty(TIMEZONE_FORMAT); 101 102 return createLayout(threadPrinting, categoryPrefixing, contextPrinting, 103 dateFormat, timezone, config); 104 } 105 106 private Layout createLayout(boolean threadPrinting, boolean categoryPrefixing, boolean contextPrinting, 107 String dateFormat, String timezone, Log4j1Configuration config) { 108 StringBuilder sb = new StringBuilder(); 109 if (dateFormat != null) { 110 if (RELATIVE.equalsIgnoreCase(dateFormat)) { 111 sb.append("%r "); 112 } else { 113 sb.append("%d{").append(dateFormat).append("}"); 114 if (timezone != null) { 115 sb.append("{").append(timezone).append("}"); 116 } 117 sb.append(" "); 118 } 119 } 120 if (threadPrinting) { 121 sb.append("[%t] "); 122 } 123 sb.append("%p "); 124 if (categoryPrefixing) { 125 sb.append("%c "); 126 } 127 if (contextPrinting) { 128 sb.append("%notEmpty{%ndc }"); 129 } 130 sb.append("- %m%n"); 131 return new LayoutWrapper(PatternLayout.newBuilder() 132 .withPattern(sb.toString()) 133 .withConfiguration(config) 134 .build()); 135 } 136}