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.Filter;
24  import org.apache.logging.log4j.core.Layout;
25  import org.apache.logging.log4j.core.config.plugins.Plugin;
26  import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
27  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
28  import org.apache.logging.log4j.core.layout.PatternLayout;
29  import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
30  
31  /**
32   * Appends log events to a given output stream using a layout.
33   * <p>
34   * Character encoding is handled within the Layout.
35   * </p>
36   */
37  @Plugin(name = "OutputStream", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
38  public final class OutputStreamAppender extends AbstractOutputStreamAppender<OutputStreamManager> {
39  
40      /**
41       * Builds OutputStreamAppender instances.
42       */
43      public static class Builder implements org.apache.logging.log4j.core.util.Builder<OutputStreamAppender> {
44  
45          private Filter filter;
46  
47          private boolean follow = false;
48  
49          private boolean ignoreExceptions = true;
50  
51          private Layout<? extends Serializable> layout = PatternLayout.createDefaultLayout();
52  
53          private String name;
54  
55          private OutputStream target;
56  
57          @Override
58          public OutputStreamAppender build() {
59              return new OutputStreamAppender(name, layout, filter, getManager(target, follow, layout), ignoreExceptions);
60          }
61  
62          public Builder setFilter(final Filter aFilter) {
63              this.filter = aFilter;
64              return this;
65          }
66  
67          public Builder setFollow(final boolean shouldFollow) {
68              this.follow = shouldFollow;
69              return this;
70          }
71  
72          public Builder setIgnoreExceptions(final boolean shouldIgnoreExceptions) {
73              this.ignoreExceptions = shouldIgnoreExceptions;
74              return this;
75          }
76  
77          public Builder setLayout(final Layout<? extends Serializable> aLayout) {
78              this.layout = aLayout;
79              return this;
80          }
81  
82          public Builder setName(final String aName) {
83              this.name = aName;
84              return this;
85          }
86  
87          public Builder setTarget(final OutputStream aTarget) {
88              this.target = aTarget;
89              return this;
90          }
91      }
92      /**
93       * Holds data to pass to factory method.
94       */
95      private static class FactoryData {
96          private final Layout<? extends Serializable> layout;
97          private final String name;
98          private final OutputStream os;
99  
100         /**
101          * Builds instances.
102          * 
103          * @param os
104          *            The OutputStream.
105          * @param type
106          *            The name of the target.
107          * @param layout
108          *            A Serializable layout
109          */
110         public FactoryData(final OutputStream os, final String type, final Layout<? extends Serializable> layout) {
111             this.os = os;
112             this.name = type;
113             this.layout = layout;
114         }
115     }
116 
117     /**
118      * Creates the manager.
119      */
120     private static class OutputStreamManagerFactory implements ManagerFactory<OutputStreamManager, FactoryData> {
121 
122         /**
123          * Creates an OutputStreamManager.
124          * 
125          * @param name
126          *            The name of the entity to manage.
127          * @param data
128          *            The data required to create the entity.
129          * @return The OutputStreamManager
130          */
131         @Override
132         public OutputStreamManager createManager(final String name, final FactoryData data) {
133             return new OutputStreamManager(data.os, data.name, data.layout, true);
134         }
135     }
136 
137     private static OutputStreamManagerFactory factory = new OutputStreamManagerFactory();
138 
139     /**
140      * Creates an OutputStream Appender.
141      * 
142      * @param layout
143      *            The layout to use or null to get the default layout.
144      * @param filter
145      *            The Filter or null.
146      * @param target
147      *            an output stream.
148      * @param follow
149      *            If true will follow changes to the underlying output stream.
150      *            Use false as the default.
151      * @param name
152      *            The name of the Appender (required).
153      * @param ignore
154      *            If {@code "true"} (default) exceptions encountered when
155      *            appending events are logged; otherwise they are propagated to
156      *            the caller. Use true as the default.
157      * @return The ConsoleAppender.
158      */
159     @PluginFactory
160     public static OutputStreamAppender createAppender(Layout<? extends Serializable> layout, final Filter filter,
161             final OutputStream target, final String name, final boolean follow, final boolean ignore) {
162         if (name == null) {
163             LOGGER.error("No name provided for OutputStreamAppender");
164             return null;
165         }
166         if (layout == null) {
167             layout = PatternLayout.createDefaultLayout();
168         }
169         return new OutputStreamAppender(name, layout, filter, getManager(target, follow, layout), ignore);
170     }
171 
172     private static OutputStreamManager getManager(final OutputStream target, final boolean follow,
173             final Layout<? extends Serializable> layout) {
174         final OutputStream os = new CloseShieldOutputStream(target);
175         final String managerName = target.getClass().getName() + "@" + Integer.toHexString(target.hashCode()) + '.'
176                 + follow;
177         return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory);
178     }
179 
180     @PluginBuilderFactory
181     public static Builder newBuilder() {
182         return new Builder();
183     }
184 
185     private OutputStreamAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
186             final OutputStreamManager manager, final boolean ignoreExceptions) {
187         super(name, layout, filter, ignoreExceptions, true, manager);
188     }
189 
190 }