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