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.rolling.action;
018    
019    import java.io.BufferedOutputStream;
020    import java.io.File;
021    import java.io.FileInputStream;
022    import java.io.FileOutputStream;
023    import java.io.IOException;
024    import java.util.zip.GZIPOutputStream;
025    
026    /**
027     * Compresses a file using GZ compression.
028     */
029    public final class GzCompressAction extends AbstractAction {
030    
031        private static final int BUF_SIZE = 8102;
032    
033        /**
034         * Source file.
035         */
036        private final File source;
037    
038        /**
039         * Destination file.
040         */
041        private final File destination;
042    
043        /**
044         * If true, attempt to delete file on completion.
045         */
046        private final boolean deleteSource;
047    
048        /**
049         * Create new instance of GzCompressAction.
050         *
051         * @param source       file to compress, may not be null.
052         * @param destination  compressed file, may not be null.
053         * @param deleteSource if true, attempt to delete file on completion.  Failure to delete
054         *                     does not cause an exception to be thrown or affect return value.
055         */
056        public GzCompressAction(final File source, final File destination, final boolean deleteSource) {
057            if (source == null) {
058                throw new NullPointerException("source");
059            }
060    
061            if (destination == null) {
062                throw new NullPointerException("destination");
063            }
064    
065            this.source = source;
066            this.destination = destination;
067            this.deleteSource = deleteSource;
068        }
069    
070        /**
071         * Compress.
072         *
073         * @return true if successfully compressed.
074         * @throws IOException on IO exception.
075         */
076        @Override
077        public boolean execute() throws IOException {
078            return execute(source, destination, deleteSource);
079        }
080    
081        /**
082         * Compress a file.
083         *
084         * @param source       file to compress, may not be null.
085         * @param destination  compressed file, may not be null.
086         * @param deleteSource if true, attempt to delete file on completion.  Failure to delete
087         *                     does not cause an exception to be thrown or affect return value.
088         * @return true if source file compressed.
089         * @throws IOException on IO exception.
090         */
091        public static boolean execute(final File source, final File destination, final boolean deleteSource)
092            throws IOException {
093            if (source.exists()) {
094                final FileInputStream fis = new FileInputStream(source);
095                final FileOutputStream fos = new FileOutputStream(destination);
096                final GZIPOutputStream gzos = new GZIPOutputStream(fos);
097                final BufferedOutputStream os = new BufferedOutputStream(gzos);
098                final byte[] inbuf = new byte[BUF_SIZE];
099                int n;
100    
101                while ((n = fis.read(inbuf)) != -1) {
102                    os.write(inbuf, 0, n);
103                }
104    
105                os.close();
106                fis.close();
107    
108                if (deleteSource && !source.delete()) {
109                    LOGGER.warn("Unable to delete " + source.toString() + '.');
110                }
111    
112                return true;
113            }
114    
115            return false;
116        }
117    
118    
119        /**
120         * Capture exception.
121         *
122         * @param ex exception.
123         */
124        @Override
125        protected void reportException(final Exception ex) {
126            LOGGER.warn("Exception during compression of '" + source.toString() + "'.", ex);
127        }
128    
129        @Override
130        public String toString() {
131            return GzCompressAction.class.getSimpleName() + '[' + source + " to " + destination //
132                    + ", deleteSource=" + deleteSource + ']';
133        }
134    }