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