001    /*
002     * Copyright 2010 the original author or authors.
003     * 
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package com.hs.mail.imap.schedule;
017    
018    import java.io.File;
019    import java.io.FilenameFilter;
020    import java.io.IOException;
021    import java.util.Date;
022    
023    import org.apache.commons.lang.time.DateFormatUtils;
024    import org.apache.commons.lang.time.DateUtils;
025    import org.apache.log4j.Logger;
026    
027    import com.hs.mail.container.config.Config;
028    import com.hs.mail.util.FileUtils;
029    
030    /**
031     * 
032     * @author Won Chul Doh
033     * @since Oct 2, 2010
034     *
035     */
036    public class MessageCompressor {
037            
038            static Logger logger = Logger.getLogger(MessageCompressor.class);
039    
040            private static final String DOT_GZIP_EXTENSION = "." + FileUtils.GZIP_EXTENSION;
041            private static final String COMPRESSED = ".compressed";
042            
043            public MessageCompressor() {
044                    super();
045            }
046            
047            public void compress(String prop, long timeLimit) {
048                    Date base = ScheduleUtils.getDateBefore(prop);
049                    if (base != null) {
050                            Date start = getStartDate(base);
051                            if (start != null) {
052                                    Date date = start;
053                                    if (logger.isDebugEnabled()) {
054                                            logger.debug("Compressing directories from "
055                                                            + DateFormatUtils.ISO_DATE_FORMAT.format(start)
056                                                            + " to "
057                                                            + DateFormatUtils.ISO_DATE_FORMAT.format(base));
058                                    }
059                                    while (date.before(base)
060                                                    && System.currentTimeMillis() < timeLimit) {
061                                            compressDirectories(date, timeLimit);
062                                            date = DateUtils.addDays(date, 1);
063                                    }
064                            }
065                    }
066            }
067            
068            public static File getDataDirectory(Date date, long physmessageid) {
069                    return new File(Config.getDataDirectory(), Config.getSubDirectory(date,
070                                    physmessageid));
071            }
072            
073            private Date getStartDate(Date date) {
074                    while (true) {
075                            File dir = getDataDirectory(date, 0).getParentFile();
076                            if (dir.exists()) {
077                                    File[] subdirs = dir.listFiles();
078                                    for (int i = 0; i < subdirs.length; i++) {
079                                            if (new File(subdirs[i], COMPRESSED).exists()) {
080                                                    return date;
081                                            }
082                                    }
083                            } else if (!dir.getParentFile().getParentFile().exists()) {
084                                    return DateUtils.addDays(date, 1);
085                            }
086                            date = DateUtils.addDays(date, -1);
087                    }
088            }
089            
090            private void compressDirectories(Date date, long timeLimit) {
091                    File directory = getDataDirectory(date, 0).getParentFile();
092                    if (directory.exists()) {
093                            File[] subdirs = directory.listFiles();
094                            for (int i = 0; i < subdirs.length
095                                            && System.currentTimeMillis() < timeLimit; i++) {
096                                    if (!new File(subdirs[i], COMPRESSED).exists()) {
097                                            if (logger.isDebugEnabled()) {
098                                                    logger.debug("Start compressing "
099                                                                    + subdirs[i].getAbsolutePath());
100                                            }
101                                            compressDirectory(subdirs[i]);
102                                    }
103                            }
104                    }
105            }
106            
107            private void compressDirectory(File directory) {
108                    File[] files = directory.listFiles(new FilenameFilter() {
109                            public boolean accept(File dir, String name) {
110                                    return !name.endsWith(DOT_GZIP_EXTENSION);
111                            }
112                    });
113                    for (int i = 0; i < files.length; i++) {
114                            compressFile(files[i]);
115                    }
116                    FileUtils.createNewFile(new File(directory, COMPRESSED));
117            }
118    
119            private void compressFile(File srcFile) {
120                    File destFile = null;
121                    try {
122                            destFile = new File(srcFile.getCanonicalPath() + DOT_GZIP_EXTENSION);
123                            FileUtils.compress(srcFile, destFile);
124                            srcFile.delete();
125                    } catch (IOException e) {
126                            if (srcFile.exists() && destFile != null && destFile.exists()) {
127                                    destFile.delete();
128                            }
129                    }
130            }
131            
132    }