com.wavemaker.tools.io.filesystem.mongo.MongoFileSystem.java Source code

Java tutorial

Introduction

Here is the source code for com.wavemaker.tools.io.filesystem.mongo.MongoFileSystem.java

Source

/*
 *  Copyright (C) 2012 VMware, Inc. All rights reserved.
 *
 *  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.
 */

package com.wavemaker.tools.io.filesystem.mongo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;

import org.springframework.util.Assert;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;
import com.wavemaker.tools.io.ResourcePath;
import com.wavemaker.tools.io.exception.ResourceException;
import com.wavemaker.tools.io.filesystem.FileSystem;
import com.wavemaker.tools.io.filesystem.JailedResourcePath;
import com.wavemaker.tools.io.filesystem.ResourceType;

/**
 * {@link FileSystem} implementation backed by a Mongo database.
 * 
 * @author Phillip Webb
 */
public class MongoFileSystem implements FileSystem<MongoFileSystemKey> {

    private static final String PARENT = "parent";

    private static final String RESOURCE_TYPE = "resourceType";

    private final ResourceOrigin resourceOrigin = ResourceOrigin.MONGO_DB;

    private final GridFS fs;

    public MongoFileSystem(DB db, String bucket) {
        Assert.notNull(db, "DB must not be null");
        Assert.notNull(bucket, "Bucket must not be null");
        this.fs = new GridFS(db, bucket);
    }

    @Override
    public MongoFileSystemKey getKey(JailedResourcePath path) {
        return new MongoFileSystemKey(path);
    }

    @Override
    public JailedResourcePath getPath(MongoFileSystemKey key) {
        return key.getPath();
    }

    @Override
    public ResourceType getResourceType(MongoFileSystemKey key) {
        GridFSDBFile file = this.fs.findOne(getFilename(key));
        if (file == null) {
            return ResourceType.DOES_NOT_EXIST;
        }
        String name = (String) file.get(RESOURCE_TYPE);
        return ResourceType.valueOf(name);
    }

    @Override
    public void createFile(MongoFileSystemKey key) {
        GridFSInputFile file = create(key, ResourceType.FILE);
        touch(file);
    }

    @Override
    public void createFolder(MongoFileSystemKey key) {
        GridFSInputFile file = create(key, ResourceType.FOLDER);
        touch(file);
    }

    private void touch(GridFSInputFile file) {
        try {
            file.getOutputStream().close();
        } catch (IOException e) {
            throw new ResourceException(e);
        }
    }

    @Override
    public Iterable<String> list(MongoFileSystemKey key) {
        BasicDBObject query = new BasicDBObject(PARENT, key.getPath().getUnjailedPath().toString());
        final DBCursor list = this.fs.getFileList(query);
        return new FileListIterable(list);
    }

    @Override
    public long getSize(MongoFileSystemKey key) {
        return getFile(key).getLength();
    }

    @Override
    public long getLastModified(MongoFileSystemKey key) {
        return getFile(key).getUploadDate().getTime();
    }

    @Override
    public InputStream getInputStream(MongoFileSystemKey key) {
        return getFile(key).getInputStream();
    }

    @Override
    public OutputStream getOutputStream(MongoFileSystemKey key) {
        delete(key);
        GridFSInputFile file = create(key, ResourceType.FILE);
        return file.getOutputStream();
    }

    @Override
    public void delete(MongoFileSystemKey key) {
        this.fs.remove(getFilename(key));
    }

    @Override
    public MongoFileSystemKey rename(MongoFileSystemKey key, String name) {
        throw new UnsupportedOperationException(); // FIXME
    }

    @Override
    public ResourceOrigin getResourceOrigin() {
        return this.resourceOrigin;
    }

    @Override
    public Object getOriginalResource() {
        throw new UnsupportedOperationException();
    }

    private GridFSInputFile create(MongoFileSystemKey key, ResourceType type) {
        Assert.notNull(type, "Type must not be null");
        Assert.state(type != ResourceType.DOES_NOT_EXIST);
        GridFSInputFile file = this.fs.createFile(getFilename(key));
        JailedResourcePath parent = key.getPath().getParent();
        if (parent != null) {
            file.put(PARENT, parent.getUnjailedPath().toString());
        }
        file.put(RESOURCE_TYPE, type.name());
        return file;
    }

    private GridFSDBFile getFile(MongoFileSystemKey key) {
        GridFSDBFile file = this.fs.findOne(getFilename(key));
        Assert.state(file != null, "File " + key.getPath() + " does not exist");
        return file;
    }

    private String getFilename(MongoFileSystemKey key) {
        return key.getPath().getUnjailedPath().toString();
    }

    @Override
    public int hashCode() {
        return this.fs.getBucketName().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        MongoFileSystem other = (MongoFileSystem) obj;
        return this.fs.getBucketName().equals(other.fs.getBucketName())
                && this.fs.getDB().getName().equals(other.fs.getDB().getName());
    }

    private static class FileListIterable implements Iterable<String> {

        private final DBCursor list;

        public FileListIterable(DBCursor list) {
            this.list = list;
        }

        @Override
        public Iterator<String> iterator() {
            return new FileListIterator(this.list.iterator());
        }
    }

    private static class FileListIterator implements Iterator<String> {

        private final Iterator<DBObject> iterator;

        public FileListIterator(Iterator<DBObject> iterator) {
            this.iterator = iterator;
        }

        @Override
        public boolean hasNext() {
            return this.iterator.hasNext();
        }

        @Override
        public String next() {
            DBObject next = this.iterator.next();
            String filename = (String) next.get("filename");
            ResourcePath path = new ResourcePath().get(filename);
            return path.getName();
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }
}