/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hive.ql.metadata;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender;
import org.apache.logging.log4j.core.appender.OutputStreamManager;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import com.google.common.annotations.VisibleForTesting;
/**
* Log4j2 appender that writers to in-memory string object.
*/
@Plugin(name = "StringAppender", category = "Core", elementType = "appender", printObject = true)
public class StringAppender
extends AbstractOutputStreamAppender<StringAppender.StringOutputStreamManager> {
private static final String APPENDER_NAME = "StringAppender";
private static LoggerContext context = (LoggerContext) LogManager.getContext(false);
private static Configuration configuration = context.getConfiguration();
private StringOutputStreamManager manager;
/**
* Instantiate a WriterAppender and set the output destination to a
* new {@link OutputStreamWriter} initialized with <code>os</code>
* as its {@link OutputStream}.
*
* @param name The name of the Appender.
* @param layout The layout to format the message.
* @param filter
* @param ignoreExceptions
* @param immediateFlush
* @param manager The OutputStreamManager.
*/
protected StringAppender(String name,
Layout<? extends Serializable> layout, Filter filter,
boolean ignoreExceptions, boolean immediateFlush,
StringOutputStreamManager manager) {
super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
this.manager = manager;
}
@PluginFactory
public static StringAppender createStringAppender(
@PluginAttribute("name") String nullablePatternString) {
PatternLayout layout;
if (nullablePatternString == null) {
layout = PatternLayout.createDefaultLayout();
} else {
layout = PatternLayout.createLayout(nullablePatternString, null, configuration,
null, null, true, false, null, null);
}
return new StringAppender(APPENDER_NAME, layout, null, false, true,
new StringOutputStreamManager(new ByteArrayOutputStream(), "StringStream", layout));
}
@VisibleForTesting
public void addToLogger(String loggerName, Level level) {
LoggerConfig loggerConfig = configuration.getLoggerConfig(loggerName);
loggerConfig.addAppender(this, level, null);
context.updateLoggers();
}
@VisibleForTesting
public void removeFromLogger(String loggerName) {
LoggerConfig loggerConfig = configuration.getLoggerConfig(loggerName);
loggerConfig.removeAppender(APPENDER_NAME);
context.updateLoggers();
}
public String getOutput() {
manager.flush();
return new String(manager.getStream().toByteArray());
}
public void reset() {
manager.reset();
}
protected static class StringOutputStreamManager extends OutputStreamManager {
ByteArrayOutputStream stream;
protected StringOutputStreamManager(ByteArrayOutputStream os, String streamName,
Layout<?> layout) {
super(os, streamName, layout, true);
stream = os;
}
public ByteArrayOutputStream getStream() {
return stream;
}
public void reset() {
stream.reset();
}
}
}