/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.sys.batch;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.config.property.ConfigurationService;
import org.kuali.rice.core.api.util.KeyValue;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
public class BatchFileUtils {
public static List<File> retrieveBatchFileLookupRootDirectories() {
ConfigurationService kualiConfigurationService = SpringContext.getBean(ConfigurationService.class);
List<File> directories = new ArrayList<File>();
String configProperty = kualiConfigurationService.getPropertyValueAsString(KFSConstants.BATCH_FILE_LOOKUP_ROOT_DIRECTORIES);
String[] directoryNames = StringUtils.split(configProperty, ";");
for (String directoryName : directoryNames) {
File rootDirectory = new File(directoryName).getAbsoluteFile();
directories.add(rootDirectory);
}
// sanity check: make sure directories are set up so that they will not present problems for pathRelativeToRootDirectory and
// resolvePathToAbsolutePath methods
for (int i = 0; i < directories.size(); i++) {
for (int j = i + 1; j < directories.size(); j++) {
File directoryI = directories.get(i);
File directoryJ = directories.get(j);
if (isPrefixOfAnother(directoryI.getAbsolutePath(), directoryJ.getAbsolutePath())) {
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");
}
if (isPrefixOfAnother(directoryI.getName(), directoryJ.getName())) {
throw new RuntimeException("Cannot have any two directories in config property batch.file.lookup.root.directories that have names that are prefix of another");
}
}
}
return directories;
}
private static boolean isPrefixOfAnother(String str1, String str2) {
return str1.startsWith(str2) || str2.startsWith(str1);
}
/**
* returns a path relative to the appropriate lookup root directory, while including the name of the root directory for example,
* if the parameter is "c:\opt\staging\gl\somefile.txt" and the roots are "c:\opt\reports;c:\opt\staging", it will return
* "staging\gl\somefile.txt" (the system-specific path separator will be used). If there are multiple matching roots, then the
* first one to be matched will take precedence
*
* @param absolutePath an absolute path for a file/directory
*/
public static String pathRelativeToRootDirectory(String absolutePath) {
for (File rootDirectory : retrieveBatchFileLookupRootDirectories()) {
if (absolutePath.startsWith(rootDirectory.getAbsolutePath())) {
return StringUtils.replaceOnce(absolutePath, rootDirectory.getAbsolutePath(), rootDirectory.getName());
}
}
throw new RuntimeException("Unable to find appropriate root directory)");
}
/**
* @param path a path string that was generated by {@link #pathRelativeToRootDirectory(String)}
* @return an absolute path, including the root directory
*/
public static String resolvePathToAbsolutePath(String path) {
for (File rootDirectory : retrieveBatchFileLookupRootDirectories()) {
if (path.startsWith(rootDirectory.getName())) {
return new File(StringUtils.replaceOnce(path, rootDirectory.getName(), rootDirectory.getAbsolutePath())).getAbsolutePath();
}
}
throw new RuntimeException("Cannot resolve to absolute path");
}
public static boolean isDirectoryAccessible(String directory) {
List<String> pathNames = null;
Class<? extends KeyValuesFinder> keyValuesFinderClass = SpringContext.getBean(DataDictionaryService.class).getAttributeValuesFinderClass(BatchFile.class, "path");
try {
if (keyValuesFinderClass != null) {
KeyValuesFinder valuesGenerator = keyValuesFinderClass.newInstance();
pathNames = new ArrayList<String>();
List<KeyValue> keyValues = valuesGenerator.getKeyValues();
for (KeyValue keyValue : keyValues) {
pathNames.add(new File(resolvePathToAbsolutePath((String) keyValue.getKey())).getAbsolutePath());
}
}
}
catch (IllegalAccessException e) {
throw new RuntimeException("can't instiantiate class " + keyValuesFinderClass, e);
}
catch (InstantiationException e) {
throw new RuntimeException("can't instiantiate class " + keyValuesFinderClass, e);
}
File directoryAbsolute = new File(directory).getAbsoluteFile();
String directoryAbsolutePath = directoryAbsolute.getAbsolutePath();
if (pathNames != null) {
if (!pathNames.contains(directoryAbsolutePath)) {
return false;
}
}
List<File> rootDirectories = retrieveBatchFileLookupRootDirectories();
for (File rootDirectory : rootDirectories) {
if (isSuperDirectoryOf(rootDirectory, directoryAbsolute)) {
return true;
}
}
return false;
}
public static boolean isSuperDirectoryOf(File superDirectory, File directory) {
superDirectory = superDirectory.getAbsoluteFile();
while (directory != null) {
directory = directory.getAbsoluteFile();
if (directory.equals(superDirectory)) {
return true;
}
directory = directory.getParentFile();
}
return false;
}
}