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.File;
020    import java.io.FileInputStream;
021    import java.io.FileOutputStream;
022    import java.io.IOException;
023    import java.util.zip.ZipEntry;
024    import java.util.zip.ZipOutputStream;
025    
026    
027    /**
028     * Compresses a file using Zip compression.
029     */
030    public final class ZipCompressAction extends AbstractAction {
031    
032        private static final int BUF_SIZE = 8102;
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         * Compression level.
051         */
052        private final int level;
053    
054        /**
055         * Create new instance of GzCompressAction.
056         *
057         * @param source       file to compress, may not be null.
058         * @param destination  compressed file, may not be null.
059         * @param deleteSource if true, attempt to delete file on completion.  Failure to delete
060         *                     does not cause an exception to be thrown or affect return value.
061         * @param level TODO
062         */
063        public ZipCompressAction(final File source, final File destination, final boolean deleteSource, final int level) {
064            if (source == null) {
065                throw new NullPointerException("source");
066            }
067    
068            if (destination == null) {
069                throw new NullPointerException("destination");
070            }
071    
072            this.source = source;
073            this.destination = destination;
074            this.deleteSource = deleteSource;
075            this.level = level;
076        }
077    
078        /**
079         * Compress.
080         *
081         * @return true if successfully compressed.
082         * @throws IOException on IO exception.
083         */
084        @Override
085        public boolean execute() throws IOException {
086            return execute(source, destination, deleteSource, level);
087        }
088    
089        /**
090         * Compress a file.
091         *
092         * @param source       file to compress, may not be null.
093         * @param destination  compressed file, may not be null.
094         * @param deleteSource if true, attempt to delete file on completion.  Failure to delete
095         *                     does not cause an exception to be thrown or affect return value.
096         * @param level the compression level
097         * @return true if source file compressed.
098         * @throws IOException on IO exception.
099         */
100        public static boolean execute(final File source, final File destination, final boolean deleteSource, final int level)
101            throws IOException {
102            if (source.exists()) {
103                final FileInputStream fis = new FileInputStream(source);
104                final FileOutputStream fos = new FileOutputStream(destination);
105                final ZipOutputStream zos = new ZipOutputStream(fos);
106                zos.setLevel(level);
107    
108                final ZipEntry zipEntry = new ZipEntry(source.getName());
109                zos.putNextEntry(zipEntry);
110    
111                final byte[] inbuf = new byte[BUF_SIZE];
112                int n;
113    
114                while ((n = fis.read(inbuf)) != -1) {
115                    zos.write(inbuf, 0, n);
116                }
117    
118                zos.close();
119                fis.close();
120    
121                if (deleteSource && !source.delete()) {
122                    LOGGER.warn("Unable to delete " + source.toString() + '.');
123                }
124    
125                return true;
126            }
127    
128            return false;
129        }
130    
131        /**
132         * Capture exception.
133         *
134         * @param ex exception.
135         */
136        @Override
137        protected void reportException(final Exception ex) {
138            LOGGER.warn("Exception during compression of '" + source.toString() + "'.", ex);
139        }
140    
141        @Override
142        public String toString() {
143            return ZipCompressAction.class.getSimpleName() + '[' + source + " to " + destination //
144                    + ", level=" + level + ", deleteSource=" + deleteSource + ']';
145        }
146    }