001/* 002 * Copyright 2009 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 */ 016package org.kuali.ole.sys.businessobject.lookup; 017 018import java.io.File; 019import java.io.IOException; 020import java.text.ParseException; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Date; 024import java.util.List; 025import java.util.Map; 026import java.util.Properties; 027 028import org.apache.commons.io.DirectoryWalker; 029import org.apache.commons.io.IOCase; 030import org.apache.commons.io.filefilter.AbstractFileFilter; 031import org.apache.commons.io.filefilter.FileFilterUtils; 032import org.apache.commons.io.filefilter.IOFileFilter; 033import org.apache.commons.io.filefilter.WildcardFileFilter; 034import org.apache.commons.lang.StringUtils; 035import org.kuali.ole.sys.batch.BatchFile; 036import org.kuali.ole.sys.batch.BatchFileUtils; 037import org.kuali.ole.sys.batch.service.BatchFileAdminAuthorizationService; 038import org.kuali.ole.sys.util.KfsDateUtils; 039import org.kuali.rice.core.api.datetime.DateTimeService; 040import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl; 041import org.kuali.rice.kns.lookup.HtmlData; 042import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData; 043import org.kuali.rice.kns.web.ui.Field; 044import org.kuali.rice.kns.web.ui.Row; 045import org.kuali.rice.krad.bo.BusinessObject; 046import org.kuali.rice.krad.util.GlobalVariables; 047import org.kuali.rice.krad.util.KRADConstants; 048import org.kuali.rice.krad.util.UrlFactory; 049 050public 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 * KRAD Conversion: gets rows after customizing the field values 152 * 153 * No use of data dictionary 154 */ 155 protected String[] getSelectedPaths() { 156 List<Row> rows = getRows(); 157 if (rows == null) { 158 return null; 159 } 160 for (Row row : rows) { 161 for (Field field : row.getFields()) { 162 if ("path".equals(field.getPropertyName()) && Field.MULTISELECT.equals(field.getFieldType())) { 163 String[] values = field.getPropertyValues(); 164 return values; 165 } 166 } 167 } 168 return null; 169 } 170 171 protected class SubDirectoryFileFilter extends AbstractFileFilter { 172 private File superDirectory; 173 174 public SubDirectoryFileFilter(File superDirectory) { 175 this.superDirectory = superDirectory.getAbsoluteFile(); 176 } 177 178 @Override 179 public boolean accept(File file) { 180 file = file.getAbsoluteFile(); 181 file = file.getParentFile(); 182 while (file != null) { 183 if (file.equals(superDirectory)) { 184 return true; 185 } 186 file = file.getParentFile(); 187 } 188 return false; 189 } 190 } 191 192 protected class LastModifiedDateFileFilter extends AbstractFileFilter { 193 private Date fromDate; 194 private Date toDate; 195 196 public LastModifiedDateFileFilter(Date fromDate, Date toDate) { 197 this.fromDate = fromDate; 198 this.toDate = toDate; 199 } 200 201 @Override 202 public boolean accept(File file) { 203 Date lastModifiedDate = KfsDateUtils.clearTimeFields(new Date(file.lastModified())); 204 205 if (fromDate != null && fromDate.after(lastModifiedDate)) { 206 return false; 207 } 208 if (toDate != null && toDate.before(lastModifiedDate)) { 209 return false; 210 } 211 return true; 212 } 213 } 214 215 protected class BatchFileFinder extends DirectoryWalker { 216 private List<BatchFile> results; 217 218 public BatchFileFinder(List<BatchFile> results, IOFileFilter fileFilter) { 219 super(null, fileFilter, -1); 220 this.results = results; 221 } 222 223 public void find(Collection<File> rootDirectories) { 224 try { 225 for (File rootDirectory : rootDirectories) { 226 walk(rootDirectory, null); 227 } 228 } 229 catch (IOException e) { 230 throw new RuntimeException("Error performing lookup", e); 231 } 232 } 233 234 /** 235 * @see org.apache.commons.io.DirectoryWalker#handleFile(java.io.File, int, java.util.Collection) 236 */ 237 @Override 238 protected void handleFile(File file, int depth, Collection results) throws IOException { 239 super.handleFile(file, depth, results); 240 BatchFile batchFile = new BatchFile(); 241 batchFile.setFile(file); 242 this.results.add(batchFile); 243 } 244 } 245 246 public void setDateTimeService(DateTimeService dateTimeService) { 247 this.dateTimeService = dateTimeService; 248 } 249 250 @Override 251 public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) { 252 List<HtmlData> links = new ArrayList<HtmlData>(); 253 254 BatchFile batchFile = (BatchFile) businessObject; 255 if (canDownloadFile(batchFile)) { 256 links.add(getDownloadUrl(batchFile)); 257 } 258 if (canDeleteFile(batchFile)) { 259 links.add(getDeleteUrl(batchFile)); 260 } 261 return links; 262 } 263 264 protected boolean canDownloadFile(BatchFile batchFile) { 265 return batchFileAdminAuthorizationService.canDownload(batchFile, GlobalVariables.getUserSession().getPerson()); 266 } 267 268 protected boolean canDeleteFile(BatchFile batchFile) { 269 return batchFileAdminAuthorizationService.canDelete(batchFile, GlobalVariables.getUserSession().getPerson()); 270 } 271 272 protected HtmlData getDownloadUrl(BatchFile batchFile) { 273 Properties parameters = new Properties(); 274 parameters.put("filePath", BatchFileUtils.pathRelativeToRootDirectory(batchFile.retrieveFile().getAbsolutePath())); 275 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "download"); 276 String href = UrlFactory.parameterizeUrl("../batchFileAdmin.do", parameters); 277 return new AnchorHtmlData(href, "download", "Download"); 278 } 279 280 protected HtmlData getDeleteUrl(BatchFile batchFile) { 281 Properties parameters = new Properties(); 282 parameters.put("filePath", BatchFileUtils.pathRelativeToRootDirectory(batchFile.retrieveFile().getAbsolutePath())); 283 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "delete"); 284 String href = UrlFactory.parameterizeUrl("../batchFileAdmin.do", parameters); 285 return new AnchorHtmlData(href, "delete", "Delete"); 286 } 287 288 /** 289 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map) 290 */ 291 @Override 292 public void validateSearchParameters(Map fieldValues) { 293 super.validateSearchParameters(fieldValues); 294 295 String[] selectedPaths = getSelectedPaths(); 296 if (selectedPaths != null) { 297 for (String selectedPath : selectedPaths) { 298 String resolvedPath = BatchFileUtils.resolvePathToAbsolutePath(selectedPath); 299 if (!BatchFileUtils.isDirectoryAccessible(resolvedPath)) { 300 throw new RuntimeException("Can't access path " + selectedPath); 301 } 302 } 303 } 304 } 305 306 /** 307 * Sets the batchFileAdminAuthorizationService attribute value. 308 * @param batchFileAdminAuthorizationService The batchFileAdminAuthorizationService to set. 309 */ 310 public void setBatchFileAdminAuthorizationService(BatchFileAdminAuthorizationService batchFileAdminAuthorizationService) { 311 this.batchFileAdminAuthorizationService = batchFileAdminAuthorizationService; 312 } 313}