View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.appender;
18  
19  import java.io.OutputStream;
20  import java.io.Serializable;
21  
22  import org.apache.logging.log4j.core.Filter;
23  import org.apache.logging.log4j.core.Layout;
24  import org.apache.logging.log4j.core.config.plugins.Plugin;
25  import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
26  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
27  import org.apache.logging.log4j.core.layout.PatternLayout;
28  import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
29  
30  /**
31   * Appends log events to a given output stream using a layout.
32   * <p>
33   * Character encoding is handled within the Layout.
34   * </p>
35   */
36  @Plugin(name = "OutputStream", category = "Core", elementType = "appender", printObject = true)
37  public final class OutputStreamAppender extends AbstractOutputStreamAppender<OutputStreamManager> {
38  
39      /**
40       * Builds OutputStreamAppender instances.
41       */
42      public static class Builder implements org.apache.logging.log4j.core.util.Builder<OutputStreamAppender> {
43  
44          private Filter filter;
45  
46          private boolean follow = false;
47  
48          private boolean ignoreExceptions = true;
49  
50          private Layout<? extends Serializable> layout = PatternLayout.createDefaultLayout();
51  
52          private String name;
53  
54          private OutputStream target;
55  
56          @Override
57          public OutputStreamAppender build() {
58              return new OutputStreamAppender(name, layout, filter, getManager(target, follow, layout), ignoreExceptions);
59          }
60  
61          public Builder setFilter(final Filter aFilter) {
62              this.filter = aFilter;
63              return this;
64          }
65  
66          public Builder setFollow(final boolean shouldFollow) {
67              this.follow = shouldFollow;
68              return this;
69          }
70  
71          public Builder setIgnoreExceptions(final boolean shouldIgnoreExceptions) {
72              this.ignoreExceptions = shouldIgnoreExceptions;
73              return this;
74          }
75  
76          public Builder setLayout(final Layout<? extends Serializable> aLayout) {
77              this.layout = aLayout;
78              return this;
79          }
80  
81          public Builder setName(final String aName) {
82              this.name = aName;
83              return this;
84          }
85  
86          public Builder setTarget(final OutputStream aTarget) {
87              this.target = aTarget;
88              return this;
89          }
90      }
91      /**
92       * Holds data to pass to factory method.
93       */
94      private static class FactoryData {
95          private final Layout<? extends Serializable> layout;
96          private final String name;
97          private final OutputStream os;
98  
99          /**
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     private static final long serialVersionUID = 1L;
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 }