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 java.util.HashMap;
020    import java.util.Map;
021    import org.apache.logging.log4j.core.Filter;
022    import org.apache.logging.log4j.core.Layout;
023    import org.apache.logging.log4j.core.LogEvent;
024    import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
025    import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
026    import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
027    import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
028    import org.apache.logging.log4j.core.config.Configuration;
029    import org.apache.logging.log4j.core.config.plugins.Plugin;
030    import org.apache.logging.log4j.core.config.plugins.PluginAttr;
031    import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
032    import org.apache.logging.log4j.core.config.plugins.PluginElement;
033    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
034    import org.apache.logging.log4j.core.layout.PatternLayout;
035    import org.apache.logging.log4j.core.net.Advertiser;
036    
037    /**
038     * An appender that writes to files and can roll over at intervals.
039     */
040    @Plugin(name = "RollingFile", type = "Core", elementType = "appender", printObject = true)
041    public final class RollingFileAppender extends AbstractOutputStreamAppender {
042    
043        private final String fileName;
044        private final String filePattern;
045        private Object advertisement;
046        private final Advertiser advertiser;
047    
048    
049        private RollingFileAppender(final String name, final Layout layout, final Filter filter,
050                                    final RollingFileManager manager, final String fileName,
051                                    final String filePattern, final boolean handleException, final boolean immediateFlush,
052                                    Advertiser advertiser) {
053            super(name, layout, filter, handleException, immediateFlush, manager);
054            if (advertiser != null)
055            {
056                Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
057                configuration.put("contentType", layout.getContentType());
058                configuration.put("name", name);
059                advertisement = advertiser.advertise(configuration);
060            }
061            this.fileName = fileName;
062            this.filePattern = filePattern;
063            this.advertiser = advertiser;
064        }
065    
066        @Override
067        public void stop() {
068            super.stop();
069            if (advertiser != null) {
070                advertiser.unadvertise(advertisement);
071            }
072        }
073    
074        /**
075         * Write the log entry rolling over the file when required.
076    
077         * @param event The LogEvent.
078         */
079        @Override
080        public void append(final LogEvent event) {
081            ((RollingFileManager) getManager()).checkRollover(event);
082            super.append(event);
083        }
084    
085        /**
086         * Returns the File name for the Appender.
087         * @return The file name.
088         */
089        public String getFileName() {
090            return fileName;
091        }
092    
093        /**
094         * Returns the file pattern used when rolling over.
095         * @return The file pattern.
096         */
097        public String getFilePattern() {
098            return filePattern;
099        }
100    
101        /**
102         * Create a RollingFileAppender.
103         * @param fileName The name of the file that is actively written to. (required).
104         * @param filePattern The pattern of the file name to use on rollover. (required).
105         * @param append If true, events are appended to the file. If false, the file
106         * is overwritten when opened. Defaults to "true"
107         * @param name The name of the Appender (required).
108         * @param bufferedIO When true, I/O will be buffered. Defaults to "true".
109         * @param immediateFlush When true, events are immediately flushed. Defaults to "true".
110         * @param policy The triggering policy. (required).
111         * @param strategy The rollover strategy. Defaults to DefaultRolloverStrategy.
112         * @param layout The layout to use (defaults to the default PatternLayout).
113         * @param filter The Filter or null.
114         * @param suppress "true" if exceptions should be hidden from the application, "false" otherwise.
115         * The default is "true".
116         * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
117         * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
118         * @param config The Configuration.
119         * @return A RollingFileAppender.
120         */
121        @PluginFactory
122        public static RollingFileAppender createAppender(@PluginAttr("fileName") final String fileName,
123                                                  @PluginAttr("filePattern") final String filePattern,
124                                                  @PluginAttr("append") final String append,
125                                                  @PluginAttr("name") final String name,
126                                                  @PluginAttr("bufferedIO") final String bufferedIO,
127                                                  @PluginAttr("immediateFlush") final String immediateFlush,
128                                                  @PluginElement("policy") final TriggeringPolicy policy,
129                                                  @PluginElement("strategy") RolloverStrategy strategy,
130                                                  @PluginElement("layout") Layout layout,
131                                                  @PluginElement("filter") final Filter filter,
132                                                  @PluginAttr("suppressExceptions") final String suppress,
133                                                  @PluginAttr("advertise") final String advertise,
134                                                  @PluginAttr("advertiseURI") final String advertiseURI,
135                                                  @PluginConfiguration final Configuration config) {
136    
137            final boolean isAppend = append == null ? true : Boolean.valueOf(append);
138            final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
139            final boolean isBuffered = bufferedIO == null ? true : Boolean.valueOf(bufferedIO);
140            final boolean isFlush = immediateFlush == null ? true : Boolean.valueOf(immediateFlush);
141            boolean isAdvertise = advertise == null ? false : Boolean.valueOf(advertise);
142            if (name == null) {
143                LOGGER.error("No name provided for FileAppender");
144                return null;
145            }
146    
147            if (fileName == null) {
148                LOGGER.error("No filename was provided for FileAppender with name "  + name);
149                return null;
150            }
151    
152            if (filePattern == null) {
153                LOGGER.error("No filename pattern provided for FileAppender with name "  + name);
154                return null;
155            }
156    
157            if (policy == null) {
158                LOGGER.error("A TriggeringPolicy must be provided");
159                return null;
160            }
161    
162            if (strategy == null) {
163                strategy = DefaultRolloverStrategy.createStrategy(null, null, "true", config);
164            }
165    
166            final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend,
167                isBuffered, policy, strategy, advertiseURI);
168            if (manager == null) {
169                return null;
170            }
171    
172            if (layout == null) {
173                layout = PatternLayout.createLayout(null, null, null, null);
174            }
175    
176            return new RollingFileAppender(name, layout, filter, manager, fileName, filePattern,
177                handleExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
178        }
179    }