001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.provider;
018
019import org.apache.commons.vfs2.FileName;
020import org.apache.commons.vfs2.FileObject;
021import org.apache.commons.vfs2.FileSystem;
022import org.apache.commons.vfs2.FileSystemException;
023import org.apache.commons.vfs2.FileSystemOptions;
024
025/**
026 * A {@link FileProvider} that is layered on top of another, such as the contents of a zip or tar file.
027 */
028public abstract class AbstractLayeredFileProvider extends AbstractFileProvider {
029    public AbstractLayeredFileProvider() {
030        super();
031        setFileNameParser(LayeredFileNameParser.getInstance());
032    }
033
034    /**
035     * Locates a file object, by absolute URI.
036     *
037     * @param baseFile The base FileObject.
038     * @param uri The name of the file to locate.
039     * @param fileSystemOptions The FileSystemOptions.
040     * @return The FileObject if it is located, null otherwise.
041     * @throws FileSystemException if an error occurs.
042     */
043    @Override
044    public FileObject findFile(final FileObject baseFile, final String uri, final FileSystemOptions fileSystemOptions)
045            throws FileSystemException {
046        // Split the URI up into its parts
047        final LayeredFileName name = (LayeredFileName) parseUri(baseFile != null ? baseFile.getName() : null, uri);
048
049        // Make the URI canonical
050
051        // Resolve the outer file name
052        final FileName fileName = name.getOuterName();
053        final FileObject file = getContext().resolveFile(baseFile, fileName.getURI(), fileSystemOptions);
054
055        // Create the file system
056        final FileObject rootFile = createFileSystem(name.getScheme(), file, fileSystemOptions);
057
058        // Resolve the file
059        return rootFile.resolveFile(name.getPath());
060    }
061
062    /**
063     * Creates a layered file system.
064     *
065     * @param scheme The protocol to use.
066     * @param file a FileObject.
067     * @param fileSystemOptions Options to access the FileSystem.
068     * @return A FileObject associated with the new FileSystem.
069     * @throws FileSystemException if an error occurs.
070     */
071    @Override
072    public synchronized FileObject createFileSystem(final String scheme, final FileObject file,
073            final FileSystemOptions fileSystemOptions) throws FileSystemException {
074        // Check if cached
075        final FileName rootName = file.getName();
076        FileSystem fs = findFileSystem(rootName, fileSystemOptions);
077        if (fs == null) {
078            // Create the file system
079            fs = doCreateFileSystem(scheme, file, fileSystemOptions);
080            addFileSystem(rootName, fs);
081        }
082        return fs.getRoot();
083    }
084
085    /**
086     * Creates a layered file system.
087     * <p>
088     * This method is called if the file system is not cached.
089     *
090     * @param scheme The URI scheme.
091     * @param file The file to create the file system on top of.
092     * @param fileSystemOptions options for new and underlying file systems.
093     * @return The file system, never null. Might implement {@link VfsComponent}.
094     * @throws FileSystemException if the file system cannot be created.
095     */
096    protected abstract FileSystem doCreateFileSystem(final String scheme, final FileObject file,
097            final FileSystemOptions fileSystemOptions) throws FileSystemException;
098
099}