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