View Javadoc
1   /*
2    * Copyright 2009 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.ole.sys.businessobject.lookup;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.text.ParseException;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Date;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Properties;
27  
28  import org.apache.commons.io.DirectoryWalker;
29  import org.apache.commons.io.IOCase;
30  import org.apache.commons.io.filefilter.AbstractFileFilter;
31  import org.apache.commons.io.filefilter.FileFilterUtils;
32  import org.apache.commons.io.filefilter.IOFileFilter;
33  import org.apache.commons.io.filefilter.WildcardFileFilter;
34  import org.apache.commons.lang.StringUtils;
35  import org.kuali.ole.sys.batch.BatchFile;
36  import org.kuali.ole.sys.batch.BatchFileUtils;
37  import org.kuali.ole.sys.batch.service.BatchFileAdminAuthorizationService;
38  import org.kuali.ole.sys.util.KfsDateUtils;
39  import org.kuali.rice.core.api.datetime.DateTimeService;
40  import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl;
41  import org.kuali.rice.kns.lookup.HtmlData;
42  import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
43  import org.kuali.rice.kns.web.ui.Field;
44  import org.kuali.rice.kns.web.ui.Row;
45  import org.kuali.rice.krad.bo.BusinessObject;
46  import org.kuali.rice.krad.util.GlobalVariables;
47  import org.kuali.rice.krad.util.KRADConstants;
48  import org.kuali.rice.krad.util.UrlFactory;
49  
50  public class BatchFileLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl {
51      protected DateTimeService dateTimeService;
52      protected BatchFileAdminAuthorizationService batchFileAdminAuthorizationService;
53      
54      @Override
55      public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
56          List<BatchFile> results = new ArrayList<BatchFile>();
57  
58          IOFileFilter filter = FileFilterUtils.fileFileFilter();
59          
60          IOFileFilter pathBasedFilter = getPathBasedFileFilter();
61          if (pathBasedFilter != null) {
62              filter = FileFilterUtils.andFileFilter(filter, pathBasedFilter);
63          }
64          
65          String fileNamePattern = fieldValues.get("fileName");
66          IOFileFilter fileNameBasedFilter = getFileNameBasedFilter(fileNamePattern);
67          if (fileNameBasedFilter != null) {
68              filter = FileFilterUtils.andFileFilter(filter, fileNameBasedFilter);
69          }
70          
71          String lastModifiedDate = fieldValues.get("lastModifiedDate");
72          IOFileFilter lastModifiedDateBasedFilter = getLastModifiedDateBasedFilter(lastModifiedDate);
73          if (lastModifiedDateBasedFilter != null) {
74              filter = FileFilterUtils.andFileFilter(filter, lastModifiedDateBasedFilter);
75          }
76          
77          BatchFileFinder finder = new BatchFileFinder(results, filter);
78          List<File> rootDirectories = BatchFileUtils.retrieveBatchFileLookupRootDirectories();
79          finder.find(rootDirectories);
80          
81          return results;
82      }
83  
84      protected IOFileFilter getPathBasedFileFilter() {
85          List<File> selectedFiles = getSelectedDirectories(getSelectedPaths());
86          if (selectedFiles.isEmpty()) {
87              return null;
88          }
89          IOFileFilter fileFilter = null;
90          for (File selectedFile : selectedFiles) {
91              IOFileFilter subFilter = new SubDirectoryFileFilter(selectedFile);
92              if (fileFilter == null) {
93                  fileFilter = subFilter;
94              }
95              else {
96                  fileFilter = FileFilterUtils.orFileFilter(fileFilter, subFilter);
97              }
98          }
99          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 }