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 }