View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.sys.batch;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.commons.lang.StringUtils;
26  import org.kuali.kfs.sys.KFSConstants;
27  import org.kuali.kfs.sys.context.SpringContext;
28  import org.kuali.rice.core.api.config.property.ConfigurationService;
29  import org.kuali.rice.core.api.util.KeyValue;
30  import org.kuali.rice.kns.service.DataDictionaryService;
31  import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
32  
33  public class BatchFileUtils {
34      public static List<File> retrieveBatchFileLookupRootDirectories() {
35          ConfigurationService kualiConfigurationService = SpringContext.getBean(ConfigurationService.class);
36          List<File> directories = new ArrayList<File>();
37          String configProperty = kualiConfigurationService.getPropertyValueAsString(KFSConstants.BATCH_FILE_LOOKUP_ROOT_DIRECTORIES);
38  
39          String[] directoryNames = StringUtils.split(configProperty, ";");
40          for (String directoryName : directoryNames) {
41              File rootDirectory = new File(directoryName).getAbsoluteFile();
42              directories.add(rootDirectory);
43          }
44  
45          // sanity check: make sure directories are set up so that they will not present problems for pathRelativeToRootDirectory and
46          // resolvePathToAbsolutePath methods
47          for (int i = 0; i < directories.size(); i++) {
48              for (int j = i + 1; j < directories.size(); j++) {
49                  File directoryI = directories.get(i);
50                  File directoryJ = directories.get(j);
51  
52                  if (isPrefixOfAnother(directoryI.getAbsolutePath(), directoryJ.getAbsolutePath())) {
53                      throw new RuntimeException("Cannot have any two directories in config property batch.file.lookup.root.directories that have absolute paths that are prefix of another");
54                  }
55                  if (isPrefixOfAnother(directoryI.getName(), directoryJ.getName())) {
56                      throw new RuntimeException("Cannot have any two directories in config property batch.file.lookup.root.directories that have names that are prefix of another");
57                  }
58              }
59          }
60          return directories;
61      }
62  
63      private static boolean isPrefixOfAnother(String str1, String str2) {
64          return str1.startsWith(str2) || str2.startsWith(str1);
65      }
66  
67      /**
68       * returns a path relative to the appropriate lookup root directory, while including the name of the root directory for example,
69       * if the parameter is "c:\opt\staging\gl\somefile.txt" and the roots are "c:\opt\reports;c:\opt\staging", it will return
70       * "staging\gl\somefile.txt" (the system-specific path separator will be used). If there are multiple matching roots, then the
71       * first one to be matched will take precedence
72       * 
73       * @param absolutePath an absolute path for a file/directory
74       */
75      public static String pathRelativeToRootDirectory(String absolutePath) {
76          for (File rootDirectory : retrieveBatchFileLookupRootDirectories()) {
77              if (absolutePath.startsWith(rootDirectory.getAbsolutePath())) {
78                  return StringUtils.replaceOnce(absolutePath, rootDirectory.getAbsolutePath(), rootDirectory.getName());
79              }
80          }
81          throw new RuntimeException("Unable to find appropriate root directory)");
82      }
83  
84  
85      /**
86       * @param path a path string that was generated by {@link #pathRelativeToRootDirectory(String)}
87       * @return an absolute path, including the root directory
88       */
89      public static String resolvePathToAbsolutePath(String path) {
90          for (File rootDirectory : retrieveBatchFileLookupRootDirectories()) {
91              if (path.startsWith(rootDirectory.getName())) {
92                  return new File(StringUtils.replaceOnce(path, rootDirectory.getName(), rootDirectory.getAbsolutePath())).getAbsolutePath();
93              }
94          }
95          throw new RuntimeException("Cannot resolve to absolute path");
96      }
97  
98      public static boolean isDirectoryAccessible(String directory) {
99          List<String> pathNames = null;
100 
101         Class<? extends KeyValuesFinder> keyValuesFinderClass = SpringContext.getBean(DataDictionaryService.class).getAttributeValuesFinderClass(BatchFile.class, "path");
102         try {
103             if (keyValuesFinderClass != null) {
104                 KeyValuesFinder valuesGenerator = keyValuesFinderClass.newInstance();
105                 pathNames = new ArrayList<String>();
106 
107                 List<KeyValue> keyValues = valuesGenerator.getKeyValues();
108                 for (KeyValue keyValue : keyValues) {
109                     pathNames.add(new File(resolvePathToAbsolutePath((String) keyValue.getKey())).getAbsolutePath());
110                 }
111             }
112         }
113         catch (IllegalAccessException e) {
114             throw new RuntimeException("can't instiantiate class " + keyValuesFinderClass, e);
115         }
116         catch (InstantiationException e) {
117             throw new RuntimeException("can't instiantiate class " + keyValuesFinderClass, e);
118         }
119 
120         File directoryAbsolute = new File(directory).getAbsoluteFile();
121         String directoryAbsolutePath = directoryAbsolute.getAbsolutePath();
122         if (pathNames != null) {
123             if (!pathNames.contains(directoryAbsolutePath)) {
124                 return false;
125             }
126         }
127 
128         List<File> rootDirectories = retrieveBatchFileLookupRootDirectories();
129         for (File rootDirectory : rootDirectories) {
130             if (isSuperDirectoryOf(rootDirectory, directoryAbsolute)) {
131                 return true;
132             }
133         }
134         return false;
135     }
136 
137     public static boolean isSuperDirectoryOf(File superDirectory, File directory) {
138         superDirectory = superDirectory.getAbsoluteFile();
139 
140         while (directory != null) {
141             directory = directory.getAbsoluteFile();
142             if (directory.equals(superDirectory)) {
143                 return true;
144             }
145             directory = directory.getParentFile();
146         }
147         return false;
148     }
149 }