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.appender; 018 019import static org.apache.log4j.builders.BuilderManager.CATEGORY; 020import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM; 021import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG; 022import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG; 023import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR; 024import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG; 025import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR; 026import static org.apache.log4j.xml.XmlConfiguration.forEachElement; 027 028import java.util.ArrayList; 029import java.util.List; 030import java.util.Properties; 031import java.util.concurrent.atomic.AtomicReference; 032 033import org.apache.log4j.Appender; 034import org.apache.log4j.Layout; 035import org.apache.log4j.bridge.AppenderWrapper; 036import org.apache.log4j.bridge.LayoutAdapter; 037import org.apache.log4j.bridge.LayoutWrapper; 038import org.apache.log4j.builders.AbstractBuilder; 039import org.apache.log4j.config.Log4j1Configuration; 040import org.apache.log4j.config.PropertiesConfiguration; 041import org.apache.log4j.spi.Filter; 042import org.apache.log4j.xml.XmlConfiguration; 043import org.apache.logging.log4j.Logger; 044import org.apache.logging.log4j.core.appender.ConsoleAppender; 045import org.apache.logging.log4j.core.config.plugins.Plugin; 046import org.apache.logging.log4j.status.StatusLogger; 047import org.w3c.dom.Element; 048 049/** 050 * Build a Console Appender 051 */ 052@Plugin(name = "org.apache.log4j.ConsoleAppender", category = CATEGORY) 053public class ConsoleAppenderBuilder extends AbstractBuilder implements AppenderBuilder { 054 private static final String SYSTEM_OUT = "System.out"; 055 private static final String SYSTEM_ERR = "System.err"; 056 private static final String TARGET = "target"; 057 058 private static final Logger LOGGER = StatusLogger.getLogger(); 059 060 public ConsoleAppenderBuilder() { 061 } 062 063 public ConsoleAppenderBuilder(String prefix, Properties props) { 064 super(prefix, props); 065 } 066 067 @Override 068 public Appender parseAppender(final Element appenderElement, final XmlConfiguration config) { 069 String name = appenderElement.getAttribute(NAME_ATTR); 070 AtomicReference<String> target = new AtomicReference<>(SYSTEM_OUT); 071 AtomicReference<Layout> layout = new AtomicReference<>(); 072 AtomicReference<List<Filter>> filters = new AtomicReference<>(new ArrayList<>()); 073 AtomicReference<String> level = new AtomicReference<>(); 074 forEachElement(appenderElement.getChildNodes(), currentElement -> { 075 switch (currentElement.getTagName()) { 076 case LAYOUT_TAG: 077 layout.set(config.parseLayout(currentElement)); 078 break; 079 case FILTER_TAG: 080 filters.get().add(config.parseFilters(currentElement)); 081 break; 082 case PARAM_TAG: { 083 switch (currentElement.getAttribute(NAME_ATTR)) { 084 case TARGET: { 085 String value = currentElement.getAttribute(VALUE_ATTR); 086 if (value == null) { 087 LOGGER.warn("No value supplied for target parameter. Defaulting to System.out."); 088 } else { 089 switch (value) { 090 case SYSTEM_OUT: 091 target.set(SYSTEM_OUT); 092 break; 093 case SYSTEM_ERR: 094 target.set(SYSTEM_ERR); 095 break; 096 default: 097 LOGGER.warn("Invalid value \"{}\" for target parameter. Using default of System.out", 098 value); 099 } 100 } 101 break; 102 } 103 case THRESHOLD_PARAM: { 104 String value = currentElement.getAttribute(VALUE_ATTR); 105 if (value == null) { 106 LOGGER.warn("No value supplied for Threshold parameter, ignoring."); 107 } else { 108 level.set(value); 109 } 110 break; 111 } 112 } 113 break; 114 } 115 } 116 }); 117 Filter head = null; 118 Filter current = null; 119 for (Filter f : filters.get()) { 120 if (head == null) { 121 head = f; 122 } else { 123 current.next = f; 124 } 125 current = f; 126 } 127 return createAppender(name, layout.get(), head, level.get(), target.get(), config); 128 } 129 130 @Override 131 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix, 132 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) { 133 Layout layout = configuration.parseLayout(layoutPrefix, name, props); 134 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name); 135 String level = getProperty(THRESHOLD_PARAM); 136 String target = getProperty(TARGET); 137 return createAppender(name, layout, filter, level, target, configuration); 138 } 139 140 private <T extends Log4j1Configuration> Appender createAppender(String name, Layout layout, Filter filter, 141 String level, String target, T configuration) { 142 org.apache.logging.log4j.core.Layout<?> consoleLayout = null; 143 144 if (layout instanceof LayoutWrapper) { 145 consoleLayout = ((LayoutWrapper) layout).getLayout(); 146 } else if (layout != null) { 147 consoleLayout = new LayoutAdapter(layout); 148 } 149 org.apache.logging.log4j.core.Filter consoleFilter = buildFilters(level, filter); 150 ConsoleAppender.Target consoleTarget = SYSTEM_ERR.equals(target) 151 ? ConsoleAppender.Target.SYSTEM_ERR : ConsoleAppender.Target.SYSTEM_OUT; 152 return new AppenderWrapper(ConsoleAppender.newBuilder() 153 .setName(name) 154 .setTarget(consoleTarget) 155 .setLayout(consoleLayout) 156 .setFilter(consoleFilter) 157 .setConfiguration(configuration) 158 .build()); 159 } 160}