use of com.mucommander.commons.file.util.FilePool in project mucommander by mucommander.
the class FileFactory method getFile.
/**
* Creates and returns an instance of AbstractFile for the given FileURL and uses the specified parent file (if any)
* as the created file's parent.
*
* <p>Specifying the file parent if an instance already exists allows to recycle the AbstractFile instance
* instead of creating a new one when the parent file is requested.
*
* @param fileURL the file URL representing the file to be created
* @param authenticator used to authenticate the specified location if its protocol
* {@link FileURL#getAuthenticationType() is authenticated} and the location contains no credentials already.
* If the value is <code>null</code>, no {@link Authenticator} will be used, not even the default one.
* @param parent the parent AbstractFile to use as the created file's parent, can be <code>null</code>
* @return an instance of {@link AbstractFile} for the given {@link FileURL}.
* @throws java.io.IOException if something went wrong during file creation.
*/
public static AbstractFile getFile(FileURL fileURL, AbstractFile parent, Authenticator authenticator, Map<String, Object> instantiationParams) throws IOException {
String protocol = fileURL.getScheme();
if (!isRegisteredProtocol(protocol))
throw new IOException("Unsupported file protocol: " + protocol);
// Lookup the pool for an existing AbstractFile instance, only if there are no instantiationParams.
// If there are instantiationParams (the file was created by the AbstractFile implementation directly, that is
// by ls()), any existing file in the pool must be replaced with a new, more up-to-date one.
FilePool filePool = FILE_POOL_MAP.get(fileURL.getScheme().toLowerCase());
if (filePool == null)
filePool = new FilePool();
if (instantiationParams.isEmpty()) {
// Note: FileURL#equals(Object) and #hashCode() take into account credentials and properties and are
// trailing slash insensitive (e.g. '/root' and '/root/' URLS are one and the same)
AbstractFile file = filePool.get(fileURL);
if (file != null)
return file;
}
String filePath = fileURL.getPath();
// For local paths under Windows (e.g. "/C:\temp"), remove the leading '/' character
if (OsFamily.WINDOWS.isCurrent() && LocalFile.SCHEMA.equals(protocol))
filePath = PathUtils.removeLeadingSeparator(filePath, "/");
String pathSeparator = fileURL.getPathSeparator();
PathTokenizer pt = new PathTokenizer(filePath, pathSeparator, false);
AbstractFile currentFile = null;
boolean lastFileResolved = false;
// If it does, create the appropriate protocol file and wrap it with an archive file.
while (pt.hasMoreFilenames()) {
String filename = pt.nextFilename();
if (SearchFile.SCHEMA.equals(protocol))
continue;
// Note that the archive can also be a directory with an archive extension.
if (isArchiveFilename(filename)) {
// Remove trailing separator of file, some file protocols such as SFTP don't like trailing separators.
// On the contrary, directories without a trailing slash are fine.
String currentPath = PathUtils.removeTrailingSeparator(pt.getCurrentPath(), pathSeparator);
// protocol file
if (currentFile == null || !currentFile.isArchive()) {
// Create a fresh FileURL with the current path
FileURL clonedURL = (FileURL) fileURL.clone();
clonedURL.setPath(currentPath);
// Look for a cached file instance before creating a new one
currentFile = filePool.get(clonedURL);
if (currentFile == null) {
currentFile = wrapArchive(createRawFile(clonedURL, authenticator, instantiationParams));
// Add the intermediate file instance to the cache
filePool.put(clonedURL, currentFile);
}
lastFileResolved = true;
} else {
// currentFile is an AbstractArchiveFile
// Note: wrapArchive() is already called by AbstractArchiveFile#createArchiveEntryFile()
AbstractFile tempEntryFile = ((AbstractArchiveFile) currentFile).getArchiveEntryFile(PathUtils.removeLeadingSeparator(currentPath.substring(currentFile.getURL().getPath().length(), currentPath.length()), pathSeparator));
if (tempEntryFile.isArchive()) {
currentFile = tempEntryFile;
lastFileResolved = true;
} else {
lastFileResolved = false;
}
// Note: don't cache the entry file
}
} else {
lastFileResolved = false;
}
}
// except that it doesn't wrap the file with an archive file
if (!lastFileResolved) {
// Note: DON'T strip out the trailing separator, as this would cause problems with root resources
String currentPath = pt.getCurrentPath();
if (currentFile == null || !currentFile.isArchive()) {
FileURL clonedURL = (FileURL) fileURL.clone();
clonedURL.setPath(currentPath);
// Note: no need to look a cached file instance, we have already looked for it at the very beginning.
currentFile = createRawFile(clonedURL, authenticator, instantiationParams);
// Add the final file instance to the cache
filePool.put(currentFile.getURL(), currentFile);
} else {
// currentFile is an AbstractArchiveFile
currentFile = ((AbstractArchiveFile) currentFile).getArchiveEntryFile(PathUtils.removeLeadingSeparator(currentPath.substring(currentFile.getURL().getPath().length(), currentPath.length()), pathSeparator));
// Note: don't cache the entry file
}
}
// Reuse existing parent file instance if one was specified
if (parent != null)
currentFile.setParent(parent);
return currentFile;
}
Aggregations