View Javadoc

1   /**
2    * Copyright 2010-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.common.util;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.List;
23  
24  import org.apache.commons.io.FileUtils;
25  import org.apache.commons.lang3.StringUtils;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  public class FileSystemUtils {
30  
31  	private static final Logger logger = LoggerFactory.getLogger(FileSystemUtils.class);
32  
33  	/**
34  	 * Examine the contents of a text file, stopping as soon as it contains <code>token</code>, or <code>timeout</code> is exceeded, whichever comes first.
35  	 */
36  	public static MonitorTextFileResult monitorTextFile(File file, String token, int intervalMillis, int timeoutMillis, String encoding) {
37  
38  		// Make sure we are configured correctly
39  		Assert.notNull(file, "file is null");
40  		Assert.hasText(token, "token has no text");
41  		Assert.hasText(encoding, "encoding has no text");
42  		Assert.isTrue(intervalMillis > 0, "interval must be a positive integer");
43  		Assert.isTrue(intervalMillis > 0, "timeout must be a positive integer");
44  
45  		// Setup some member variables to record what happens
46  		long start = System.currentTimeMillis();
47  		long stop = start + timeoutMillis;
48  		boolean exists = false;
49  		boolean contains = false;
50  		boolean timeoutExceeded = false;
51  		long now = -1;
52  		String content = null;
53  
54  		// loop until timeout is exceeded or we find the token inside the file
55  		for (;;) {
56  
57  			// Always pause (unless this is the first iteration)
58  			if (now != -1) {
59  				ThreadUtils.sleep(intervalMillis);
60  			}
61  
62  			// Check to make sure we haven't exceeded our timeout limit
63  			now = System.currentTimeMillis();
64  			if (now > stop) {
65  				timeoutExceeded = true;
66  				break;
67  			}
68  
69  			// If the file does not exist, no point in going any further
70  			exists = LocationUtils.exists(file);
71  			if (!exists) {
72  				continue;
73  			}
74  
75  			// The file exists, check to see if the token we are looking for is present in the file
76  			content = LocationUtils.toString(file, encoding);
77  			contains = StringUtils.contains(content, token);
78  			if (contains) {
79  				// We found what we are looking for, we are done
80  				break;
81  			}
82  		}
83  
84  		// Record how long the overall process took
85  		long elapsed = now - start;
86  
87  		// Fill in a pojo detailing what happened
88  		MonitorTextFileResult mtfr = new MonitorTextFileResult(exists, contains, timeoutExceeded, elapsed);
89  		mtfr.setAbsolutePath(LocationUtils.getCanonicalPath(file));
90  		mtfr.setContent(content);
91  		return mtfr;
92  	}
93  
94  	public static List<SyncResult> syncFiles(List<SyncRequest> requests) throws IOException {
95  		List<SyncResult> results = new ArrayList<SyncResult>();
96  		for (SyncRequest request : requests) {
97  			SyncResult result = syncFiles(request);
98  			results.add(result);
99  		}
100 		return results;
101 	}
102 
103 	public static SyncResult syncFiles(SyncRequest request) throws IOException {
104 		logger.info("Sync [{}] -> [{}]", request.getSrcDir(), request.getDstDir());
105 		List<File> dstFiles = getAllFiles(request.getDstDir());
106 		List<File> srcFiles = request.getSrcFiles();
107 
108 		List<String> dstPaths = getRelativePaths(request.getDstDir(), dstFiles);
109 		List<String> srcPaths = getRelativePaths(request.getSrcDir(), srcFiles);
110 
111 		List<String> adds = new ArrayList<String>();
112 		List<String> updates = new ArrayList<String>();
113 		List<String> deletes = new ArrayList<String>();
114 
115 		for (String srcPath : srcPaths) {
116 			boolean existing = dstPaths.contains(srcPath);
117 			if (existing) {
118 				updates.add(srcPath);
119 			} else {
120 				adds.add(srcPath);
121 			}
122 		}
123 		for (String dstPath : dstPaths) {
124 			boolean extra = !srcPaths.contains(dstPath);
125 			if (extra) {
126 				deletes.add(dstPath);
127 			}
128 		}
129 
130 		copyFiles(request.getSrcDir(), request.getSrcFiles(), request.getDstDir());
131 
132 		SyncResult result = new SyncResult();
133 		result.setAdds(getFullPaths(request.getDstDir(), adds));
134 		result.setUpdates(getFullPaths(request.getDstDir(), updates));
135 		result.setDeletes(getFullPaths(request.getDstDir(), deletes));
136 		return result;
137 	}
138 
139 	protected static void copyFiles(File srcDir, List<File> files, File dstDir) throws IOException {
140 		for (File file : files) {
141 			String relativePath = getRelativePath(srcDir, file);
142 			File dstFile = new File(dstDir, relativePath);
143 			FileUtils.copyFile(file, dstFile);
144 		}
145 	}
146 
147 	protected static List<File> getFullPaths(File dir, List<String> relativePaths) {
148 		List<File> files = new ArrayList<File>();
149 		for (String relativePath : relativePaths) {
150 			File file = new File(dir, relativePath);
151 			files.add(file);
152 		}
153 		return files;
154 	}
155 
156 	protected static List<String> getRelativePaths(File dir, List<File> files) {
157 		List<String> relativePaths = new ArrayList<String>();
158 		for (File file : files) {
159 			String relativePath = getRelativePath(dir, file);
160 			relativePaths.add(relativePath);
161 		}
162 		return relativePaths;
163 	}
164 
165 	protected static String getRelativePath(File dir, File file) {
166 		String dirPath = LocationUtils.getCanonicalPath(dir);
167 		String filePath = LocationUtils.getCanonicalPath(file);
168 		if (!StringUtils.contains(filePath, dirPath)) {
169 			throw new IllegalArgumentException(file + " does not reside under " + dir);
170 		}
171 		return StringUtils.remove(filePath, dirPath);
172 	}
173 
174 	protected static List<File> getAllFiles(File dir) {
175 		SimpleScanner scanner = new SimpleScanner(dir, Arrays.asList("**/*"), Arrays.asList("**/.svn/**", "**/.git/**"));
176 		return scanner.getFiles();
177 	}
178 
179 }