001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache license, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License. You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the license for the specific language governing permissions and
015     * limitations under the license.
016     */
017    package org.apache.logging.log4j.core.appender;
018    
019    import org.apache.logging.log4j.core.Filter;
020    import org.apache.logging.log4j.core.Layout;
021    import org.apache.logging.log4j.core.LogEvent;
022    import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
023    import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
024    import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
025    import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
026    import org.apache.logging.log4j.core.config.Configuration;
027    import org.apache.logging.log4j.core.config.plugins.Plugin;
028    import org.apache.logging.log4j.core.config.plugins.PluginAttr;
029    import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
030    import org.apache.logging.log4j.core.config.plugins.PluginElement;
031    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
032    import org.apache.logging.log4j.core.layout.PatternLayout;
033    import org.apache.logging.log4j.core.net.Advertiser;
034    
035    import java.io.Serializable;
036    import java.util.HashMap;
037    import java.util.Map;
038    
039    /**
040     * An appender that writes to files and can roll over at intervals.
041     */
042    @Plugin(name = "RollingFile", category = "Core", elementType = "appender", printObject = true)
043    public final class RollingFileAppender<T extends Serializable> extends AbstractOutputStreamAppender<T> {
044    
045        private final String fileName;
046        private final String filePattern;
047        private Object advertisement;
048        private final Advertiser advertiser;
049    
050    
051        private RollingFileAppender(final String name, final Layout<T> layout, final Filter filter,
052                                    final RollingFileManager manager, final String fileName,
053                                    final String filePattern, final boolean handleException, final boolean immediateFlush,
054                                    Advertiser advertiser) {
055            super(name, layout, filter, handleException, immediateFlush, manager);
056            if (advertiser != null)
057            {
058                Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
059                configuration.put("contentType", layout.getContentType());
060                configuration.put("name", name);
061                advertisement = advertiser.advertise(configuration);
062            }
063            this.fileName = fileName;
064            this.filePattern = filePattern;
065            this.advertiser = advertiser;
066        }
067    
068        @Override
069        public void stop() {
070            super.stop();
071            if (advertiser != null) {
072                advertiser.unadvertise(advertisement);
073            }
074        }
075    
076        /**
077         * Write the log entry rolling over the file when required.
078    
079         * @param event The LogEvent.
080         */
081        @Override
082        public void append(final LogEvent event) {
083            ((RollingFileManager) getManager()).checkRollover(event);
084            super.append(event);
085        }
086    
087        /**
088         * Returns the File name for the Appender.
089         * @return The file name.
090         */
091        public String getFileName() {
092            return fileName;
093        }
094    
095        /**
096         * Returns the file pattern used when rolling over.
097         * @return The file pattern.
098         */
099        public String getFilePattern() {
100            return filePattern;
101        }
102    
103        /**
104         * Create a RollingFileAppender.
105         * @param fileName The name of the file that is actively written to. (required).
106         * @param filePattern The pattern of the file name to use on rollover. (required).
107         * @param append If true, events are appended to the file. If false, the file
108         * is overwritten when opened. Defaults to "true"
109         * @param name The name of the Appender (required).
110         * @param bufferedIO When true, I/O will be buffered. Defaults to "true".
111         * @param immediateFlush When true, events are immediately flushed. Defaults to "true".
112         * @param policy The triggering policy. (required).
113         * @param strategy The rollover strategy. Defaults to DefaultRolloverStrategy.
114         * @param layout The layout to use (defaults to the default PatternLayout).
115         * @param filter The Filter or null.
116         * @param suppress "true" if exceptions should be hidden from the application, "false" otherwise.
117         * The default is "true".
118         * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
119         * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
120         * @param config The Configuration.
121         * @return A RollingFileAppender.
122         */
123        @PluginFactory
124        public static <S extends Serializable> RollingFileAppender<S> createAppender(
125                                                  @PluginAttr("fileName") final String fileName,
126                                                  @PluginAttr("filePattern") final String filePattern,
127                                                  @PluginAttr("append") final String append,
128                                                  @PluginAttr("name") final String name,
129                                                  @PluginAttr("bufferedIO") final String bufferedIO,
130                                                  @PluginAttr("immediateFlush") final String immediateFlush,
131                                                  @PluginElement("policy") final TriggeringPolicy policy,
132                                                  @PluginElement("strategy") RolloverStrategy strategy,
133                                                  @PluginElement("layout") Layout<S> layout,
134                                                  @PluginElement("filter") final Filter filter,
135                                                  @PluginAttr("suppressExceptions") final String suppress,
136                                                  @PluginAttr("advertise") final String advertise,
137                                                  @PluginAttr("advertiseURI") final String advertiseURI,
138                                                  @PluginConfiguration final Configuration config) {
139    
140            final boolean isAppend = append == null ? true : Boolean.valueOf(append);
141            final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
142            final boolean isBuffered = bufferedIO == null ? true : Boolean.valueOf(bufferedIO);
143            final boolean isFlush = immediateFlush == null ? true : Boolean.valueOf(immediateFlush);
144            boolean isAdvertise = advertise == null ? false : Boolean.valueOf(advertise);
145            if (name == null) {
146                LOGGER.error("No name provided for FileAppender");
147                return null;
148            }
149    
150            if (fileName == null) {
151                LOGGER.error("No filename was provided for FileAppender with name "  + name);
152                return null;
153            }
154    
155            if (filePattern == null) {
156                LOGGER.error("No filename pattern provided for FileAppender with name "  + name);
157                return null;
158            }
159    
160            if (policy == null) {
161                LOGGER.error("A TriggeringPolicy must be provided");
162                return null;
163            }
164    
165            if (strategy == null) {
166                strategy = DefaultRolloverStrategy.createStrategy(null, null, "true", config);
167            }
168    
169            if (layout == null) {
170                @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
171                Layout<S> l = (Layout<S>)PatternLayout.createLayout(null, null, null, null, null);
172                layout = l;
173            }
174    
175            final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend,
176                isBuffered, policy, strategy, advertiseURI, layout);
177            if (manager == null) {
178                return null;
179            }
180    
181            return new RollingFileAppender<S>(name, layout, filter, manager, fileName, filePattern,
182                handleExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
183        }
184    }