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.Appender;
23  import org.apache.logging.log4j.core.Core;
24  import org.apache.logging.log4j.core.Filter;
25  import org.apache.logging.log4j.core.Layout;
26  import org.apache.logging.log4j.core.config.plugins.Plugin;
27  import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
28  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29  import org.apache.logging.log4j.core.layout.PatternLayout;
30  import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
31  
32  /**
33   * Appends log events to a given output stream using a layout.
34   * <p>
35   * Character encoding is handled within the Layout.
36   * </p>
37   */
38  @Plugin(name = "OutputStream", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
39  public final class OutputStreamAppender extends AbstractOutputStreamAppender<OutputStreamManager> {
40  
41      /**
42       * Builds OutputStreamAppender instances.
43       */
44      public static class Builder implements org.apache.logging.log4j.core.util.Builder<OutputStreamAppender> {
45  
46          private Filter filter;
47  
48          private boolean follow = false;
49  
50          private boolean ignoreExceptions = true;
51  
52          private Layout<? extends Serializable> layout = PatternLayout.createDefaultLayout();
53  
54          private String name;
55  
56          private OutputStream target;
57  
58          @Override
59          public OutputStreamAppender build() {
60              return new OutputStreamAppender(name, layout, filter, getManager(target, follow, layout), ignoreExceptions);
61          }
62  
63          public Builder setFilter(final Filter aFilter) {
64              this.filter = aFilter;
65              return this;
66          }
67  
68          public Builder setFollow(final boolean shouldFollow) {
69              this.follow = shouldFollow;
70              return this;
71          }
72  
73          public Builder setIgnoreExceptions(final boolean shouldIgnoreExceptions) {
74              this.ignoreExceptions = shouldIgnoreExceptions;
75              return this;
76          }
77  
78          public Builder setLayout(final Layout<? extends Serializable> aLayout) {
79              this.layout = aLayout;
80              return this;
81          }
82  
83          public Builder setName(final String aName) {
84              this.name = aName;
85              return this;
86          }
87  
88          public Builder setTarget(final OutputStream aTarget) {
89              this.target = aTarget;
90              return this;
91          }
92      }
93      /**
94       * Holds data to pass to factory method.
95       */
96      private static class FactoryData {
97          private final Layout<? extends Serializable> layout;
98          private final String name;
99          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 }