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     /**
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 }