001 /*
002 * Copyright 2011 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.kfs.sys.businessobject.lookup;
017
018 import java.io.File;
019 import java.io.IOException;
020 import java.text.ParseException;
021 import java.util.ArrayList;
022 import java.util.Collection;
023 import java.util.Date;
024 import java.util.List;
025 import java.util.Map;
026 import java.util.Properties;
027
028 import org.apache.commons.io.DirectoryWalker;
029 import org.apache.commons.io.IOCase;
030 import org.apache.commons.io.filefilter.AbstractFileFilter;
031 import org.apache.commons.io.filefilter.FileFilterUtils;
032 import org.apache.commons.io.filefilter.IOFileFilter;
033 import org.apache.commons.io.filefilter.WildcardFileFilter;
034 import org.apache.commons.lang.StringUtils;
035 import org.kuali.kfs.sys.batch.BatchFile;
036 import org.kuali.kfs.sys.batch.BatchFileUtils;
037 import org.kuali.kfs.sys.batch.service.BatchFileAdminAuthorizationService;
038 import org.kuali.rice.kns.bo.BusinessObject;
039 import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl;
040 import org.kuali.rice.kns.lookup.HtmlData;
041 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
042 import org.kuali.rice.kns.service.DateTimeService;
043 import org.kuali.rice.kns.util.DateUtils;
044 import org.kuali.rice.kns.util.GlobalVariables;
045 import org.kuali.rice.kns.util.KNSConstants;
046 import org.kuali.rice.kns.util.UrlFactory;
047 import org.kuali.rice.kns.web.ui.Field;
048 import org.kuali.rice.kns.web.ui.Row;
049
050 public class BatchFileLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl {
051 protected DateTimeService dateTimeService;
052 protected BatchFileAdminAuthorizationService batchFileAdminAuthorizationService;
053
054 @Override
055 public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
056 List<BatchFile> results = new ArrayList<BatchFile>();
057
058 IOFileFilter filter = FileFilterUtils.fileFileFilter();
059
060 IOFileFilter pathBasedFilter = getPathBasedFileFilter();
061 if (pathBasedFilter != null) {
062 filter = FileFilterUtils.andFileFilter(filter, pathBasedFilter);
063 }
064
065 String fileNamePattern = fieldValues.get("fileName");
066 IOFileFilter fileNameBasedFilter = getFileNameBasedFilter(fileNamePattern);
067 if (fileNameBasedFilter != null) {
068 filter = FileFilterUtils.andFileFilter(filter, fileNameBasedFilter);
069 }
070
071 String lastModifiedDate = fieldValues.get("lastModifiedDate");
072 IOFileFilter lastModifiedDateBasedFilter = getLastModifiedDateBasedFilter(lastModifiedDate);
073 if (lastModifiedDateBasedFilter != null) {
074 filter = FileFilterUtils.andFileFilter(filter, lastModifiedDateBasedFilter);
075 }
076
077 BatchFileFinder finder = new BatchFileFinder(results, filter);
078 List<File> rootDirectories = BatchFileUtils.retrieveBatchFileLookupRootDirectories();
079 finder.find(rootDirectories);
080
081 return results;
082 }
083
084 protected IOFileFilter getPathBasedFileFilter() {
085 List<File> selectedFiles = getSelectedDirectories(getSelectedPaths());
086 if (selectedFiles.isEmpty()) {
087 return null;
088 }
089 IOFileFilter fileFilter = null;
090 for (File selectedFile : selectedFiles) {
091 IOFileFilter subFilter = new SubDirectoryFileFilter(selectedFile);
092 if (fileFilter == null) {
093 fileFilter = subFilter;
094 }
095 else {
096 fileFilter = FileFilterUtils.orFileFilter(fileFilter, subFilter);
097 }
098 }
099 return fileFilter;
100 }
101
102 protected IOFileFilter getFileNameBasedFilter(String fileNamePattern) {
103 if (StringUtils.isNotBlank(fileNamePattern)) {
104 return new WildcardFileFilter(fileNamePattern, IOCase.INSENSITIVE);
105 }
106 return null;
107 }
108
109 protected IOFileFilter getLastModifiedDateBasedFilter(String lastModifiedDatePattern) {
110 if (StringUtils.isBlank(lastModifiedDatePattern)) {
111 return null;
112 }
113 try {
114 if (lastModifiedDatePattern.startsWith("<=")) {
115 String dateString = StringUtils.removeStart(lastModifiedDatePattern, "<=");
116 Date toDate = dateTimeService.convertToDate(dateString);
117 return new LastModifiedDateFileFilter(null, toDate);
118 }
119 if (lastModifiedDatePattern.startsWith(">=")) {
120 String dateString = StringUtils.removeStart(lastModifiedDatePattern, ">=");
121 Date fromDate = dateTimeService.convertToDate(dateString);
122 return new LastModifiedDateFileFilter(fromDate, null);
123 }
124 if (lastModifiedDatePattern.contains("..")) {
125 String[] dates = StringUtils.splitByWholeSeparator(lastModifiedDatePattern, "..", 2);
126 Date fromDate = dateTimeService.convertToDate(dates[0]);
127 Date toDate = dateTimeService.convertToDate(dates[1]);
128 return new LastModifiedDateFileFilter(fromDate, toDate);
129 }
130 }
131 catch (ParseException e) {
132 throw new RuntimeException("Can't parse date", e);
133 }
134 throw new RuntimeException("Unable to perform search using last modified date " + lastModifiedDatePattern);
135 }
136
137 protected List<File> getSelectedDirectories(String[] selectedPaths) {
138 List<File> directories = new ArrayList<File>();
139 if (selectedPaths != null) {
140 for (String selectedPath : selectedPaths) {
141 File directory = new File(BatchFileUtils.resolvePathToAbsolutePath(selectedPath));
142 if (!directory.exists()) {
143 throw new RuntimeException("Non existent directory " + BatchFileUtils.resolvePathToAbsolutePath(selectedPath));
144 }
145 directories.add(directory);
146 }
147 }
148 return directories;
149 }
150
151 protected String[] getSelectedPaths() {
152 List<Row> rows = getRows();
153 if (rows == null) {
154 return null;
155 }
156 for (Row row : rows) {
157 for (Field field : row.getFields()) {
158 if ("path".equals(field.getPropertyName()) && Field.MULTISELECT.equals(field.getFieldType())) {
159 String[] values = field.getPropertyValues();
160 return values;
161 }
162 }
163 }
164 return null;
165 }
166
167 protected class SubDirectoryFileFilter extends AbstractFileFilter {
168 private File superDirectory;
169
170 public SubDirectoryFileFilter(File superDirectory) {
171 this.superDirectory = superDirectory.getAbsoluteFile();
172 }
173
174 @Override
175 public boolean accept(File file) {
176 file = file.getAbsoluteFile();
177 file = file.getParentFile();
178 while (file != null) {
179 if (file.equals(superDirectory)) {
180 return true;
181 }
182 file = file.getParentFile();
183 }
184 return false;
185 }
186 }
187
188 protected class LastModifiedDateFileFilter extends AbstractFileFilter {
189 private Date fromDate;
190 private Date toDate;
191
192 public LastModifiedDateFileFilter(Date fromDate, Date toDate) {
193 this.fromDate = fromDate;
194 this.toDate = toDate;
195 }
196
197 @Override
198 public boolean accept(File file) {
199 Date lastModifiedDate = DateUtils.clearTimeFields(new Date(file.lastModified()));
200
201 if (fromDate != null && fromDate.after(lastModifiedDate)) {
202 return false;
203 }
204 if (toDate != null && toDate.before(lastModifiedDate)) {
205 return false;
206 }
207 return true;
208 }
209 }
210
211 protected class BatchFileFinder extends DirectoryWalker {
212 private List<BatchFile> results;
213
214 public BatchFileFinder(List<BatchFile> results, IOFileFilter fileFilter) {
215 super(null, fileFilter, -1);
216 this.results = results;
217 }
218
219 public void find(Collection<File> rootDirectories) {
220 try {
221 for (File rootDirectory : rootDirectories) {
222 walk(rootDirectory, null);
223 }
224 }
225 catch (IOException e) {
226 throw new RuntimeException("Error performing lookup", e);
227 }
228 }
229
230 /**
231 * @see org.apache.commons.io.DirectoryWalker#handleFile(java.io.File, int, java.util.Collection)
232 */
233 @Override
234 protected void handleFile(File file, int depth, Collection results) throws IOException {
235 super.handleFile(file, depth, results);
236 BatchFile batchFile = new BatchFile();
237 batchFile.setFile(file);
238 this.results.add(batchFile);
239 }
240 }
241
242 public void setDateTimeService(DateTimeService dateTimeService) {
243 this.dateTimeService = dateTimeService;
244 }
245
246 @Override
247 public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
248 List<HtmlData> links = new ArrayList<HtmlData>();
249
250 BatchFile batchFile = (BatchFile) businessObject;
251 if (canDownloadFile(batchFile)) {
252 links.add(getDownloadUrl(batchFile));
253 }
254 if (canDeleteFile(batchFile)) {
255 links.add(getDeleteUrl(batchFile));
256 }
257 return links;
258 }
259
260 protected boolean canDownloadFile(BatchFile batchFile) {
261 return batchFileAdminAuthorizationService.canDownload(batchFile, GlobalVariables.getUserSession().getPerson());
262 }
263
264 protected boolean canDeleteFile(BatchFile batchFile) {
265 return batchFileAdminAuthorizationService.canDelete(batchFile, GlobalVariables.getUserSession().getPerson());
266 }
267
268 protected HtmlData getDownloadUrl(BatchFile batchFile) {
269 Properties parameters = new Properties();
270 parameters.put("filePath", BatchFileUtils.pathRelativeToRootDirectory(batchFile.retrieveFile().getAbsolutePath()));
271 parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, "download");
272 String href = UrlFactory.parameterizeUrl("../batchFileAdmin.do", parameters);
273 return new AnchorHtmlData(href, "download", "Download");
274 }
275
276 protected HtmlData getDeleteUrl(BatchFile batchFile) {
277 Properties parameters = new Properties();
278 parameters.put("filePath", BatchFileUtils.pathRelativeToRootDirectory(batchFile.retrieveFile().getAbsolutePath()));
279 parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, "delete");
280 String href = UrlFactory.parameterizeUrl("../batchFileAdmin.do", parameters);
281 return new AnchorHtmlData(href, "delete", "Delete");
282 }
283
284 /**
285 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
286 */
287 @Override
288 public void validateSearchParameters(Map fieldValues) {
289 super.validateSearchParameters(fieldValues);
290
291 String[] selectedPaths = getSelectedPaths();
292 if (selectedPaths != null) {
293 for (String selectedPath : selectedPaths) {
294 String resolvedPath = BatchFileUtils.resolvePathToAbsolutePath(selectedPath);
295 if (!BatchFileUtils.isDirectoryAccessible(resolvedPath)) {
296 throw new RuntimeException("Can't access path " + selectedPath);
297 }
298 }
299 }
300 }
301
302 /**
303 * Sets the batchFileAdminAuthorizationService attribute value.
304 * @param batchFileAdminAuthorizationService The batchFileAdminAuthorizationService to set.
305 */
306 public void setBatchFileAdminAuthorizationService(BatchFileAdminAuthorizationService batchFileAdminAuthorizationService) {
307 this.batchFileAdminAuthorizationService = batchFileAdminAuthorizationService;
308 }
309 }