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.Core;
23  import org.apache.logging.log4j.core.Filter;
24  import org.apache.logging.log4j.core.StringLayout;
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.CloseShieldWriter;
30  
31  /**
32   * Appends log events to a {@link Writer}.
33   */
34  @Plugin(name = "Writer", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
35  public final class WriterAppender extends AbstractWriterAppender<WriterManager> {
36  
37      /**
38       * Builds WriterAppender instances.
39       */
40      public static class Builder implements org.apache.logging.log4j.core.util.Builder<WriterAppender> {
41  
42          private Filter filter;
43  
44          private boolean follow = false;
45  
46          private boolean ignoreExceptions = true;
47  
48          private StringLayout layout = PatternLayout.createDefaultLayout();
49  
50          private String name;
51  
52          private Writer target;
53  
54          @Override
55          public WriterAppender build() {
56              return new WriterAppender(name, layout, filter, getManager(target, follow, layout), ignoreExceptions);
57          }
58  
59          public Builder setFilter(final Filter aFilter) {
60              this.filter = aFilter;
61              return this;
62          }
63  
64          public Builder setFollow(final boolean shouldFollow) {
65              this.follow = shouldFollow;
66              return this;
67          }
68  
69          public Builder setIgnoreExceptions(final boolean shouldIgnoreExceptions) {
70              this.ignoreExceptions = shouldIgnoreExceptions;
71              return this;
72          }
73  
74          public Builder setLayout(final StringLayout aLayout) {
75              this.layout = aLayout;
76              return this;
77          }
78  
79          public Builder setName(final String aName) {
80              this.name = aName;
81              return this;
82          }
83  
84          public Builder setTarget(final Writer aTarget) {
85              this.target = aTarget;
86              return this;
87          }
88      }
89      /**
90       * Holds data to pass to factory method.
91       */
92      private static class FactoryData {
93          private final StringLayout layout;
94          private final String name;
95          private final Writer writer;
96  
97          /**
98           * Builds instances.
99           * 
100          * @param writer
101          *            The OutputStream.
102          * @param type
103          *            The name of the target.
104          * @param layout
105          *            A String layout
106          */
107         public FactoryData(final Writer writer, final String type, final StringLayout layout) {
108             this.writer = writer;
109             this.name = type;
110             this.layout = layout;
111         }
112     }
113 
114     private static class WriterManagerFactory implements ManagerFactory<WriterManager, FactoryData> {
115 
116         /**
117          * Creates a WriterManager.
118          * 
119          * @param name
120          *            The name of the entity to manage.
121          * @param data
122          *            The data required to create the entity.
123          * @return The WriterManager
124          */
125         @Override
126         public WriterManager createManager(final String name, final FactoryData data) {
127             return new WriterManager(data.writer, data.name, data.layout, true);
128         }
129     }
130 
131     private static WriterManagerFactory factory = new WriterManagerFactory();
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 }