com.lemania.sis.server.servlet.GcsServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.lemania.sis.server.servlet.GcsServlet.java

Source

/*
 * Copyright 2013 Google 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.lemania.sis.server.servlet;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.tools.cloudstorage.GcsFileOptions;
import com.google.appengine.tools.cloudstorage.GcsFilename;
import com.google.appengine.tools.cloudstorage.GcsInputChannel;
import com.google.appengine.tools.cloudstorage.GcsOutputChannel;
import com.google.appengine.tools.cloudstorage.GcsService;
import com.google.appengine.tools.cloudstorage.GcsServiceFactory;
import com.google.appengine.tools.cloudstorage.RetryParams;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.Channels;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * A simple servlet that proxies reads and writes to its Google Cloud Storage
 * bucket.
 */
@MultipartConfig
@SuppressWarnings("serial")
public class GcsServlet extends HttpServlet {

    public static final boolean SERVE_USING_BLOBSTORE_API = false;

    /**
     * This is where backoff parameters are configured. Here it is aggressively
     * retrying with backoff, up to 10 times but taking no more that 15 seconds
     * total to do so.
     */
    private final GcsService gcsService = GcsServiceFactory.createGcsService(new RetryParams.Builder()
            .initialRetryDelayMillis(10).retryMaxAttempts(10).totalRetryPeriodMillis(15000).build());

    /**
     * Used below to determine the size of chucks to read in. Should be > 1kb
     * and < 10MB
     */
    private static final int BUFFER_SIZE = 2 * 1024 * 1024;

    /**
     * Retrieves a file from GCS and returns it in the http response. If the
     * request path is /gcs/Foo/Bar this will be interpreted as a request to
     * read the GCS file named Bar in the bucket Foo.
     */
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //
        GcsFilename fileName = getFileName(req);
        //
        resp.setContentType("application/octet-stream");
        resp.setHeader("Content-Disposition:", "attachment;filename=" + fileName.getObjectName());
        //
        if (SERVE_USING_BLOBSTORE_API) {
            BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
            BlobKey blobKey = blobstoreService
                    .createGsBlobKey("/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName());
            blobstoreService.serve(blobKey, resp);
        } else {
            GcsInputChannel readChannel = gcsService.openPrefetchingReadChannel(fileName, 0, BUFFER_SIZE);
            copy(Channels.newInputStream(readChannel), resp.getOutputStream());
        }
    }

    /**
     * Writes the payload of the incoming post as the contents of a file to GCS.
     * If the request path is /gcs/Foo/Bar this will be interpreted as a request
     * to create a GCS file named Bar in bucket Foo.
     * 
     * @throws ServletException
     */
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        //
        GcsOutputChannel outputChannel = gcsService.createOrReplace(getFileName(req),
                GcsFileOptions.getDefaultInstance());

        ServletFileUpload upload = new ServletFileUpload();
        resp.setContentType("text/plain");
        //
        InputStream fileContent = null;
        FileItemIterator iterator;
        try {
            iterator = upload.getItemIterator(req);
            while (iterator.hasNext()) {
                FileItemStream item = iterator.next();
                InputStream stream = item.openStream();

                if (item.isFormField()) {
                    //
                } else {
                    fileContent = stream;
                    break;
                }
            }
        } catch (FileUploadException e) {
            //
            e.printStackTrace();
        }
        //
        copy(fileContent, Channels.newOutputStream(outputChannel));
    }

    /*
     * */
    private GcsFilename getFileName(HttpServletRequest req) {
        //
        String[] splits = req.getRequestURI().split("/", 4);
        if (!splits[0].equals("") || !splits[1].equals("gcs")) {
            throw new IllegalArgumentException(
                    "The URL is not formed as expected. " + "Expecting /gcs/<bucket>/<object>");
        }

        // AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();

        String filename;
        String fullPath = splits[3];
        int startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
        if (startIndex > -1) {
            filename = fullPath.substring(startIndex);
            if (filename.indexOf('\\') == 0 || filename.indexOf('/') == 0) {
                filename = filename.substring(1);
            }
        } else {
            filename = fullPath;
        }

        // return new GcsFilename( appIdentity.getDefaultGcsBucketName() , filename );

        return new GcsFilename(splits[2], splits[3]);
    }

    /**
     * Transfer the data from the inputStream to the outputStream. Then close
     * both streams.
     */
    private void copy(InputStream input, OutputStream output) throws IOException {
        try {
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead = input.read(buffer);
            while (bytesRead != -1) {
                output.write(buffer, 0, bytesRead);
                bytesRead = input.read(buffer);
            }
        } finally {
            input.close();
            output.close();
        }
    }
}