001    /**
002     * Copyright 2010-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 org.kuali.common.util;
017    
018    import java.io.File;
019    import java.io.IOException;
020    import java.util.ArrayList;
021    import java.util.Arrays;
022    import java.util.List;
023    
024    import org.apache.commons.io.FileUtils;
025    import org.apache.commons.lang3.StringUtils;
026    import org.slf4j.Logger;
027    import org.slf4j.LoggerFactory;
028    
029    public class FileSystemUtils {
030    
031            private static final Logger logger = LoggerFactory.getLogger(FileSystemUtils.class);
032    
033            public static List<SyncResult> syncFiles(List<SyncRequest> requests) throws IOException {
034                    List<SyncResult> results = new ArrayList<SyncResult>();
035                    for (SyncRequest request : requests) {
036                            SyncResult result = syncFiles(request);
037                            results.add(result);
038                    }
039                    return results;
040            }
041    
042            public static SyncResult syncFiles(SyncRequest request) throws IOException {
043                    logger.info("Sync [{}] -> [{}]", request.getSrcDir(), request.getDstDir());
044                    List<File> dstFiles = getAllFiles(request.getDstDir());
045                    List<File> srcFiles = request.getSrcFiles();
046    
047                    List<String> dstPaths = getRelativePaths(request.getDstDir(), dstFiles);
048                    List<String> srcPaths = getRelativePaths(request.getSrcDir(), srcFiles);
049    
050                    List<String> adds = new ArrayList<String>();
051                    List<String> updates = new ArrayList<String>();
052                    List<String> deletes = new ArrayList<String>();
053    
054                    for (String srcPath : srcPaths) {
055                            boolean existing = dstPaths.contains(srcPath);
056                            if (existing) {
057                                    updates.add(srcPath);
058                            } else {
059                                    adds.add(srcPath);
060                            }
061                    }
062                    for (String dstPath : dstPaths) {
063                            boolean extra = !srcPaths.contains(dstPath);
064                            if (extra) {
065                                    deletes.add(dstPath);
066                            }
067                    }
068    
069                    copyFiles(request.getSrcDir(), request.getSrcFiles(), request.getDstDir());
070    
071                    SyncResult result = new SyncResult();
072                    result.setAdds(getFullPaths(request.getDstDir(), adds));
073                    result.setUpdates(getFullPaths(request.getDstDir(), updates));
074                    result.setDeletes(getFullPaths(request.getDstDir(), deletes));
075                    return result;
076            }
077    
078            protected static void copyFiles(File srcDir, List<File> files, File dstDir) throws IOException {
079                    for (File file : files) {
080                            String relativePath = getRelativePath(srcDir, file);
081                            File dstFile = new File(dstDir, relativePath);
082                            FileUtils.copyFile(file, dstFile);
083                    }
084            }
085    
086            protected static List<File> getFullPaths(File dir, List<String> relativePaths) {
087                    List<File> files = new ArrayList<File>();
088                    for (String relativePath : relativePaths) {
089                            File file = new File(dir, relativePath);
090                            files.add(file);
091                    }
092                    return files;
093            }
094    
095            protected static List<String> getRelativePaths(File dir, List<File> files) {
096                    List<String> relativePaths = new ArrayList<String>();
097                    for (File file : files) {
098                            String relativePath = getRelativePath(dir, file);
099                            relativePaths.add(relativePath);
100                    }
101                    return relativePaths;
102            }
103    
104            protected static String getRelativePath(File dir, File file) {
105                    String dirPath = LocationUtils.getCanonicalPath(dir);
106                    String filePath = LocationUtils.getCanonicalPath(file);
107                    if (!StringUtils.contains(filePath, dirPath)) {
108                            throw new IllegalArgumentException(file + " does not reside under " + dir);
109                    }
110                    return StringUtils.remove(filePath, dirPath);
111            }
112    
113            protected static List<File> getAllFiles(File dir) {
114                    SimpleScanner scanner = new SimpleScanner(dir, Arrays.asList("**/*"), Arrays.asList("**/.svn/**", "**/.git/**"));
115                    return scanner.getFiles();
116            }
117    
118    }