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.logging.log4j.core.appender; 018 019import java.io.OutputStream; 020import java.io.Serializable; 021 022import org.apache.logging.log4j.core.Appender; 023import org.apache.logging.log4j.core.Core; 024import org.apache.logging.log4j.core.Filter; 025import org.apache.logging.log4j.core.Layout; 026import org.apache.logging.log4j.core.config.Property; 027import org.apache.logging.log4j.core.config.plugins.Plugin; 028import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; 029import org.apache.logging.log4j.core.config.plugins.PluginFactory; 030import org.apache.logging.log4j.core.layout.PatternLayout; 031import org.apache.logging.log4j.core.util.CloseShieldOutputStream; 032import org.apache.logging.log4j.core.util.NullOutputStream; 033 034/** 035 * Appends log events to a given output stream using a layout. 036 * <p> 037 * Character encoding is handled within the Layout. 038 * </p> 039 */ 040@Plugin(name = "OutputStream", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) 041public final class OutputStreamAppender extends AbstractOutputStreamAppender<OutputStreamManager> { 042 043 /** 044 * Builds OutputStreamAppender instances. 045 * 046 * @param <B> 047 * The type to build. 048 */ 049 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B> 050 implements org.apache.logging.log4j.core.util.Builder<OutputStreamAppender> { 051 052 private boolean follow = false; 053 054 private final boolean ignoreExceptions = true; 055 056 private OutputStream target; 057 058 @Override 059 public OutputStreamAppender build() { 060 final Layout<? extends Serializable> layout = getLayout(); 061 final Layout<? extends Serializable> actualLayout = layout == null ? PatternLayout.createDefaultLayout() 062 : layout; 063 return new OutputStreamAppender(getName(), actualLayout, getFilter(), getManager(target, follow, actualLayout), 064 ignoreExceptions, getPropertyArray()); 065 } 066 067 public B setFollow(final boolean shouldFollow) { 068 this.follow = shouldFollow; 069 return asBuilder(); 070 } 071 072 public B setTarget(final OutputStream aTarget) { 073 this.target = aTarget; 074 return asBuilder(); 075 } 076 } 077 078 /** 079 * Holds data to pass to factory method. 080 */ 081 private static class FactoryData { 082 private final Layout<? extends Serializable> layout; 083 private final String name; 084 private final OutputStream os; 085 086 /** 087 * Builds instances. 088 * 089 * @param os 090 * The OutputStream. 091 * @param type 092 * The name of the target. 093 * @param layout 094 * A Serializable layout 095 */ 096 public FactoryData(final OutputStream os, final String type, final Layout<? extends Serializable> layout) { 097 this.os = os; 098 this.name = type; 099 this.layout = layout; 100 } 101 } 102 103 /** 104 * Creates the manager. 105 */ 106 private static class OutputStreamManagerFactory implements ManagerFactory<OutputStreamManager, FactoryData> { 107 108 /** 109 * Creates an OutputStreamManager. 110 * 111 * @param name 112 * The name of the entity to manage. 113 * @param data 114 * The data required to create the entity. 115 * @return The OutputStreamManager 116 */ 117 @Override 118 public OutputStreamManager createManager(final String name, final FactoryData data) { 119 return new OutputStreamManager(data.os, data.name, data.layout, true); 120 } 121 } 122 123 private static OutputStreamManagerFactory factory = new OutputStreamManagerFactory(); 124 125 /** 126 * Creates an OutputStream Appender. 127 * 128 * @param layout 129 * The layout to use or null to get the default layout. 130 * @param filter 131 * The Filter or null. 132 * @param target 133 * an output stream. 134 * @param follow 135 * If true will follow changes to the underlying output stream. 136 * Use false as the default. 137 * @param name 138 * The name of the Appender (required). 139 * @param ignore 140 * If {@code "true"} (default) exceptions encountered when 141 * appending events are logged; otherwise they are propagated to 142 * the caller. Use true as the default. 143 * @return The ConsoleAppender. 144 */ 145 @PluginFactory 146 public static OutputStreamAppender createAppender(Layout<? extends Serializable> layout, final Filter filter, 147 final OutputStream target, final String name, final boolean follow, final boolean ignore) { 148 if (name == null) { 149 LOGGER.error("No name provided for OutputStreamAppender"); 150 return null; 151 } 152 if (layout == null) { 153 layout = PatternLayout.createDefaultLayout(); 154 } 155 return new OutputStreamAppender(name, layout, filter, getManager(target, follow, layout), ignore, null); 156 } 157 158 private static OutputStreamManager getManager(final OutputStream target, final boolean follow, 159 final Layout<? extends Serializable> layout) { 160 final OutputStream os = target == null ? NullOutputStream.getInstance() : new CloseShieldOutputStream(target); 161 final OutputStream targetRef = target == null ? os : target; 162 final String managerName = targetRef.getClass().getName() + "@" + Integer.toHexString(targetRef.hashCode()) 163 + '.' + follow; 164 return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory); 165 } 166 167 @PluginBuilderFactory 168 public static <B extends Builder<B>> B newBuilder() { 169 return new Builder<B>().asBuilder(); 170 } 171 172 private OutputStreamAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter, 173 final OutputStreamManager manager, final boolean ignoreExceptions, final Property[] properties) { 174 super(name, layout, filter, ignoreExceptions, true, properties, manager); 175 } 176 177}