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