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