com.thinkberg.moxo.vfs.s3.jets3t.Jets3tFileObject.java Source code

Java tutorial

Introduction

Here is the source code for com.thinkberg.moxo.vfs.s3.jets3t.Jets3tFileObject.java

Source

/*
 * Copyright 2007 Matthias L. Jugel.
 *
 * 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.thinkberg.moxo.vfs.s3.jets3t;

import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.provider.AbstractFileObject;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.utils.Mimetypes;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.Date;

/**
 * Implementation of the virtual S3 file system object using the Jets3t library.
 *
 * @author Matthias L. Jugel
 */
public class Jets3tFileObject extends AbstractFileObject {
    private final S3Service service;
    private final S3Bucket bucket;

    private boolean attached = false;
    private boolean changed = false;
    private S3Object object;
    private File cacheFile;

    public Jets3tFileObject(FileName fileName, Jets3tFileSystem fileSystem, S3Service service, S3Bucket bucket)
            throws FileSystemException {
        super(fileName, fileSystem);
        this.service = service;
        this.bucket = bucket;
    }

    protected void doAttach() throws Exception {
        if (!attached) {
            try {
                object = service.getObject(bucket, getS3Key());
                System.err.println("Attached file to S3 Object: " + object);
                InputStream is = object.getDataInputStream();
                if (object.getContentLength() > 0) {
                    ReadableByteChannel rbc = Channels.newChannel(is);
                    FileChannel cacheFc = getCacheFileChannel();
                    cacheFc.transferFrom(rbc, 0, object.getContentLength());
                    cacheFc.close();
                    rbc.close();
                } else {
                    is.close();
                }
            } catch (S3ServiceException e) {
                object = new S3Object(bucket, getS3Key());
                object.setLastModifiedDate(new Date());
                System.err.println("Attached file to new S3 Object: " + object);
            }
            attached = true;
        }
    }

    protected void doDetach() throws Exception {
        // TODO do not send immediately but put in some kind of upload queue
        if (attached && changed) {
            System.err.println("Detaching changed object: " + object);
            if (cacheFile != null) {
                FileChannel cacheFc = getCacheFileChannel();
                object.setContentLength(cacheFc.size());
                object.setDataInputStream(getInputStream());
            }
            System.err.println(object);
            service.putObject(bucket, object);
            attached = false;
        }
    }

    protected void doDelete() throws Exception {
        service.deleteObject(bucket, object.getKey());
    }

    protected void doRename(FileObject newfile) throws Exception {
        super.doRename(newfile);
    }

    protected void doCreateFolder() throws Exception {
        if (!Mimetypes.MIMETYPE_JETS3T_DIRECTORY.equals(object.getContentType())) {
            object.setContentType(Mimetypes.MIMETYPE_JETS3T_DIRECTORY);
            service.putObject(bucket, object);
            changed = false;
        }
    }

    protected long doGetLastModifiedTime() throws Exception {
        return object.getLastModifiedDate().getTime();
    }

    protected void doSetLastModifiedTime(final long modtime) throws Exception {
        changed = true;
        object.setLastModifiedDate(new Date(modtime));
    }

    protected InputStream doGetInputStream() throws Exception {
        return Channels.newInputStream(getCacheFileChannel());
    }

    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception {
        changed = true;
        return Channels.newOutputStream(getCacheFileChannel());
    }

    protected FileType doGetType() throws Exception {
        if (null == object.getContentType()) {
            return FileType.IMAGINARY;
        }

        String contentType = object.getContentType();
        if ("".equals(object.getKey()) || Mimetypes.MIMETYPE_JETS3T_DIRECTORY.equals(contentType)) {
            return FileType.FOLDER;
        }

        return FileType.FILE;
    }

    protected String[] doListChildren() throws Exception {
        String path = object.getKey();
        // make sure we add a '/' slash at the end to find children
        if (!"".equals(path)) {
            path = path + "/";
        }

        S3Object[] children = service.listObjects(bucket, path, "/");
        String[] childrenNames = new String[children.length];
        for (int i = 0; i < children.length; i++) {
            if (!children[i].getKey().equals(path)) {
                // strip path from name (leave only base name)
                childrenNames[i] = children[i].getKey().replaceAll("[^/]*//*", "");
            }
        }
        return childrenNames;
    }

    protected long doGetContentSize() throws Exception {
        return object.getContentLength();
    }

    // Utility methods
    /**
     * Create an S3 key from a commons-vfs path. This simply
     * strips the slash from the beginning if it exists.
     *
     * @return the S3 object key
     */
    private String getS3Key() {
        String path = getName().getPath();
        if ("".equals(path)) {
            return path;
        } else {
            return path.substring(1);
        }
    }

    private FileChannel getCacheFileChannel() throws IOException {
        if (cacheFile == null) {
            cacheFile = File.createTempFile("moxo.", ".s3");
        }
        return new RandomAccessFile(cacheFile, "rw").getChannel();
    }
}