org.efaps.webdav4vfs.test.ramvfs.RamFileSystem.java Source code

Java tutorial

Introduction

Here is the source code for org.efaps.webdav4vfs.test.ramvfs.RamFileSystem.java

Source

/*
 * Copyright 2003 - 2010 The eFaps Team
 * Copyright 2002 - 2006 Apache Software Foundation (ASF)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.webdav4vfs.test.ramvfs;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.provider.AbstractFileSystem;
import org.apache.commons.vfs.provider.local.LocalFileName;

/**
 * A RAM File System.
 *
 * @author The eFaps Team
 * @author <a href="http://commons.apache.org/vfs/team-list.html">Apache Commons VFS team</a>
 * @version $Id$
 */
public class RamFileSystem extends AbstractFileSystem implements Serializable {
    /**
     * Unique identifier used to serialize.
     */
    private static final long serialVersionUID = 5587421059149890672L;

    /**
     * Cache of RAM File Data.
     */
    private Map<FileName, RamFileData> cache = Collections.synchronizedMap(new HashMap<FileName, RamFileData>());

    /**
     * @param _rootName             root file name
     * @param _fileSystemOptions    file system options
     */
    protected RamFileSystem(final FileName _rootName, final FileSystemOptions _fileSystemOptions) {
        super(_rootName, null, _fileSystemOptions);
        // create root
        final RamFileData rootData = new RamFileData(_rootName);
        rootData.setType(FileType.FOLDER);
        rootData.setLastModified(System.currentTimeMillis());
        this.cache.put(_rootName, rootData);
    }

    /**
     * {@inheritDoc}
     */
    @Override()
    protected FileObject createFile(final FileName _name) {
        return new RamFileObject(_name, this);
    }

    /**
     * {@inheritDoc}
     */
    @Override()
    @SuppressWarnings("unchecked")
    protected void addCapabilities(final Collection _caps) {
        _caps.addAll(RamFileProvider.CAPABILITIES);
    }

    /**
     * @param _name The name of the file.
     * @return children The names of the children.
     */
    String[] listChildren(final FileName _name) {
        final String[] names;
        final RamFileData data = this.cache.get(_name);
        if ((data == null) || !data.getType().hasChildren()) {
            names = null;
        } else {
            final Collection<RamFileData> children = data.getChildren();

            names = new String[children.size()];

            int pos = 0;
            for (final RamFileData childData : children) {
                names[pos] = childData.getName().getBaseName();
                pos++;
            }
        }
        return names;
    }

    /**
     * Delete a file.
     *
     * @param _file     file to delete
     * @throws FileSystemException if file could not be deleted
     */
    void delete(final RamFileObject _file) throws FileSystemException {
        // root is read only check
        if (_file.getParent() == null) {
            throw new FileSystemException("unable to delete root");
        }

        // Remove reference from cache
        this.cache.remove(_file.getName());
        // Notify the parent
        final RamFileObject parent = (RamFileObject) this.resolveFile(_file.getParent().getName());
        parent.getData().removeChild(_file.getData());
        parent.close();
        // close the file
        _file.getData().clear();
        _file.close();
    }

    /**
     * Saves a file.
     *
     * @param _fileObject   file object to save
     * @throws FileSystemException if file object could not be saved
     */
    void save(final RamFileObject _fileObject) throws FileSystemException {

        // Validate name
        if (_fileObject.getData().getName() == null) {
            throw new FileSystemException(new IllegalStateException("The data has no name. " + _fileObject));
        }

        // Add to the parent
        if (_fileObject.getName().getDepth() > 0) {
            final RamFileData parentData = this.cache.get(_fileObject.getParent().getName());
            // Only if not already added
            if (!parentData.hasChildren(_fileObject.getData())) {
                final RamFileObject parent = (RamFileObject) _fileObject.getParent();
                parent.getData().addChild(_fileObject.getData());
                parent.close();
            }
        }
        // Store in cache
        this.cache.put(_fileObject.getName(), _fileObject.getData());
        _fileObject.getData().updateLastModified();
        _fileObject.close();
    }

    /**
     * Moves the original file <code>_from</code> to the new file
     * <code>_to</code>.
     *
     * @param _from     original file
     * @param _to       new file.
     * @throws FileSystemException if an error occurs
     */
    void rename(final RamFileObject _from, final RamFileObject _to) throws FileSystemException {
        if (!this.cache.containsKey(_from.getName())) {
            throw new FileSystemException("File does not exist: " + _from.getName());
        }
        // copy data
        _to.getData().setBuffer(_from.getData().getBuffer());
        _to.getData().setLastModified(_from.getData().getLastModified());
        _to.getData().setType(_from.getData().getType());
        _to.getData().getAttributes().clear();
        _to.getData().getAttributes().putAll(_from.getData().getAttributes());
        // fix problem that the file name of the data was cleared
        _to.getData().setName(_to.getName());

        this.save(_to);

        // copy children
        if (_from.getType() == FileType.FOLDER) {
            for (final FileObject child : _from.getChildren()) {
                final FileName newFileName = ((LocalFileName) _to.getName()).createName(
                        _to.getName().getPath() + "/" + child.getName().getBaseName(), child.getName().getType());
                this.rename((RamFileObject) child, new RamFileObject(newFileName, this));
            }
        }

        this.delete(_from);
    }

    /**
     * Attach the related file data to the file object <code>_fo</code>.
     *
     * @param _fo   file object to attach
     */
    public void attach(final RamFileObject _fo) {
        if (_fo.getName() == null) {
            throw new IllegalArgumentException("Null argument");
        }
        RamFileData data = this.cache.get(_fo.getName());
        if (data == null) {
            data = new RamFileData(_fo.getName());
        }
        _fo.setData(data);
    }

    /**
     * Import a Tree.
     *
     * @param _file The File
     * @throws FileSystemException if an error occurs.
     */
    public void importTree(final File _file) throws FileSystemException {
        final FileObject fileFo = getFileSystemManager().toFileObject(_file);
        this.toRamFileObject(fileFo, fileFo);
    }

    /**
     * Import the given file with the name relative to the given root.
     *
     * @param _fo       file object
     * @param _root     root file object
     * @throws FileSystemException if file object could not be imported
     */
    void toRamFileObject(final FileObject _fo, final FileObject _root) throws FileSystemException {
        final RamFileObject memFo = (RamFileObject) this
                .resolveFile(_fo.getName().getPath().substring(_root.getName().getPath().length()));
        if (_fo.getType().hasChildren()) {
            // Create Folder
            memFo.createFolder();
            // Import recursively
            final FileObject[] fos = _fo.getChildren();
            for (int i = 0; i < fos.length; i++) {
                final FileObject child = fos[i];
                this.toRamFileObject(child, _root);
            }
        } else if (_fo.getType().equals(FileType.FILE)) {
            // Read bytes
            try {
                final InputStream is = _fo.getContent().getInputStream();
                try {
                    final OutputStream os = new BufferedOutputStream(memFo.getOutputStream(), 512);
                    int i;
                    while ((i = is.read()) != -1) {
                        os.write(i);
                    }
                    os.flush();
                    os.close();
                } finally {
                    try {
                        is.close();
                    } catch (final IOException e) {
                        // ignore on close exception
                    }
                }
            } catch (final IOException e) {
                throw new FileSystemException(e.getClass().getName() + " " + e.getMessage());
            }
        } else {
            throw new FileSystemException("File is not a folder nor a file " + memFo);
        }
    }

    /**
     * @return Returns the size of the FileSystem
     */
    int size() {
        int size = 0;
        for (final RamFileData data : this.cache.values()) {
            size += data.size();
        }
        return size;
    }

    /**
     * Close the RAMFileSystem.
     */
    @Override()
    public void close() {
        this.cache = null;
        super.close();
    }
}