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