Search in sources :

Example 1 with PathTokenizer

use of com.mucommander.commons.file.util.PathTokenizer 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;
}
Also used : PathTokenizer(com.mucommander.commons.file.util.PathTokenizer) AbstractArchiveFile(com.mucommander.commons.file.archive.AbstractArchiveFile) FilePool(com.mucommander.commons.file.util.FilePool) IOException(java.io.IOException)

Aggregations

AbstractArchiveFile (com.mucommander.commons.file.archive.AbstractArchiveFile)1 FilePool (com.mucommander.commons.file.util.FilePool)1 PathTokenizer (com.mucommander.commons.file.util.PathTokenizer)1 IOException (java.io.IOException)1