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