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.APPENDER_REF_TAG; 021import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM; 022import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR; 023import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG; 024import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR; 025import static org.apache.log4j.xml.XmlConfiguration.forEachElement; 026 027import java.util.ArrayList; 028import java.util.List; 029import java.util.Properties; 030import java.util.concurrent.atomic.AtomicBoolean; 031import java.util.concurrent.atomic.AtomicReference; 032 033import org.apache.log4j.Appender; 034import org.apache.log4j.bridge.AppenderWrapper; 035import org.apache.log4j.builders.AbstractBuilder; 036import org.apache.log4j.config.Log4j1Configuration; 037import org.apache.log4j.config.PropertiesConfiguration; 038import org.apache.log4j.helpers.OptionConverter; 039import org.apache.log4j.xml.XmlConfiguration; 040import org.apache.logging.log4j.Logger; 041import org.apache.logging.log4j.core.appender.AsyncAppender; 042import org.apache.logging.log4j.core.config.AppenderRef; 043import org.apache.logging.log4j.core.config.plugins.Plugin; 044import org.apache.logging.log4j.status.StatusLogger; 045import org.apache.logging.log4j.util.Strings; 046import org.w3c.dom.Element; 047 048 049/** 050 * Build an Asynch Appender 051 */ 052@Plugin(name = "org.apache.log4j.AsyncAppender", category = CATEGORY) 053public class AsyncAppenderBuilder extends AbstractBuilder implements AppenderBuilder { 054 055 private static final Logger LOGGER = StatusLogger.getLogger(); 056 private static final String BLOCKING_PARAM = "Blocking"; 057 private static final String INCLUDE_LOCATION_PARAM = "IncludeLocation"; 058 059 public AsyncAppenderBuilder() { 060 } 061 062 public AsyncAppenderBuilder(String prefix, Properties props) { 063 super(prefix, props); 064 } 065 066 @Override 067 public Appender parseAppender(final Element appenderElement, final XmlConfiguration config) { 068 String name = appenderElement.getAttribute(NAME_ATTR); 069 AtomicReference<List<String>> appenderRefs = new AtomicReference<>(new ArrayList<>()); 070 AtomicBoolean blocking = new AtomicBoolean(); 071 AtomicBoolean includeLocation = new AtomicBoolean(); 072 AtomicReference<String> level = new AtomicReference<>("trace"); 073 AtomicReference<Integer> bufferSize = new AtomicReference<>(1024); 074 forEachElement(appenderElement.getChildNodes(), currentElement -> { 075 switch (currentElement.getTagName()) { 076 case APPENDER_REF_TAG: 077 Appender appender = config.findAppenderByReference(currentElement); 078 if (appender != null) { 079 appenderRefs.get().add(appender.getName()); 080 } 081 break; 082 case PARAM_TAG: { 083 switch (currentElement.getAttribute(NAME_ATTR)) { 084 case BUFFER_SIZE_PARAM: { 085 String value = currentElement.getAttribute(VALUE_ATTR); 086 if (value == null) { 087 LOGGER.warn("No value supplied for BufferSize parameter. Defaulting to 1024."); 088 } else { 089 bufferSize.set(Integer.parseInt(value)); 090 } 091 break; 092 } 093 case BLOCKING_PARAM: { 094 String value = currentElement.getAttribute(VALUE_ATTR); 095 if (value == null) { 096 LOGGER.warn("No value supplied for Blocking parameter. Defaulting to false."); 097 } else { 098 blocking.set(Boolean.parseBoolean(value)); 099 } 100 break; 101 } 102 case INCLUDE_LOCATION_PARAM: { 103 String value = currentElement.getAttribute(VALUE_ATTR); 104 if (value == null) { 105 LOGGER.warn("No value supplied for IncludeLocation parameter. Defaulting to false."); 106 } else { 107 includeLocation.set(Boolean.parseBoolean(value)); 108 } 109 break; 110 } 111 case THRESHOLD_PARAM: { 112 String value = currentElement.getAttribute(VALUE_ATTR); 113 if (value == null) { 114 LOGGER.warn("No value supplied for Threshold parameter, ignoring."); 115 } else { 116 level.set(value); 117 } 118 break; 119 } 120 } 121 break; 122 } 123 } 124 }); 125 return createAppender(name, level.get(), appenderRefs.get().toArray(Strings.EMPTY_ARRAY), blocking.get(), 126 bufferSize.get(), includeLocation.get(), config); 127 } 128 129 @Override 130 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix, 131 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) { 132 String appenderRef = getProperty(APPENDER_REF_TAG); 133 boolean blocking = getBooleanProperty(BLOCKING_PARAM); 134 boolean includeLocation = getBooleanProperty(INCLUDE_LOCATION_PARAM); 135 String level = getProperty(THRESHOLD_PARAM); 136 int bufferSize = getIntegerProperty(BUFFER_SIZE_PARAM, 1024); 137 if (appenderRef == null) { 138 LOGGER.warn("No appender references configured for AsyncAppender {}", name); 139 return null; 140 } 141 Appender appender = configuration.parseAppender(props, appenderRef); 142 if (appender == null) { 143 LOGGER.warn("Cannot locate Appender {}", appenderRef); 144 return null; 145 } 146 return createAppender(name, level, new String[] {appenderRef}, blocking, bufferSize, includeLocation, 147 configuration); 148 } 149 150 private <T extends Log4j1Configuration> Appender createAppender(String name, String level, 151 String[] appenderRefs, boolean blocking, int bufferSize, boolean includeLocation, 152 T configuration) { 153 org.apache.logging.log4j.Level logLevel = OptionConverter.convertLevel(level, 154 org.apache.logging.log4j.Level.TRACE); 155 AppenderRef[] refs = new AppenderRef[appenderRefs.length]; 156 int index = 0; 157 for (String appenderRef : appenderRefs) { 158 refs[index++] = AppenderRef.createAppenderRef(appenderRef, logLevel, null); 159 } 160 return new AppenderWrapper(AsyncAppender.newBuilder() 161 .setName(name) 162 .setAppenderRefs(refs) 163 .setBlocking(blocking) 164 .setBufferSize(bufferSize) 165 .setIncludeLocation(includeLocation) 166 .setConfiguration(configuration) 167 .build()); 168 } 169}