org.magnum.dataup.VideoSvcCtrl.java Source code

Java tutorial

Introduction

Here is the source code for org.magnum.dataup.VideoSvcCtrl.java

Source

/*
 * 
 * Copyright 2014 Jules White
 *
 * 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 org.magnum.dataup;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.magnum.dataup.model.Video;
import org.magnum.dataup.model.VideoStatus;
import org.magnum.dataup.model.VideoStatus.VideoState;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class VideoSvcCtrl {

    /**
     * You will need to create one or more Spring controllers to fulfill the
     * requirements of the assignment. If you use this file, please rename it
     * to something other than "AnEmptyController"
     * 
     * 
        ________  ________  ________  ________          ___       ___  ___  ________  ___  __       
       |\   ____\|\   __  \|\   __  \|\   ___ \        |\  \     |\  \|\  \|\   ____\|\  \|\  \     
       \ \  \___|\ \  \|\  \ \  \|\  \ \  \_|\ \       \ \  \    \ \  \\\  \ \  \___|\ \  \/  /|_   
        \ \  \  __\ \  \\\  \ \  \\\  \ \  \ \\ \       \ \  \    \ \  \\\  \ \  \    \ \   ___  \  
    \ \  \|\  \ \  \\\  \ \  \\\  \ \  \_\\ \       \ \  \____\ \  \\\  \ \  \____\ \  \\ \  \ 
     \ \_______\ \_______\ \_______\ \_______\       \ \_______\ \_______\ \_______\ \__\\ \__\
      \|_______|\|_______|\|_______|\|_______|        \|_______|\|_______|\|_______|\|__| \|__|
        
     * 
     */

    // Initialize a list of videos that the controller will maintain in memory
    private final Map<Long, Video> videos = new HashMap<Long, Video>();

    private static AtomicLong currentId = new AtomicLong(0L);

    private VideoFileManager mVideoFileManager;

    public static final String DATA_PARAMETER = "data";
    public static final String ID_PARAMETER = "id";
    public static final String VIDEO_SVC_PATH = "/video";
    public static final String VIDEO_DATA_PATH = VIDEO_SVC_PATH + "/{id}/data";
    public static final String ERROR_MSG = "video not found";

    @RequestMapping(value = VIDEO_SVC_PATH, method = RequestMethod.GET)
    public @ResponseBody Collection<Video> getVideoList() {

        return videos.values();
    }

    /**
     * POST /video
     * 
     * The video metadata is provided as an application/json request
     * body. The JSON should generate a valid instance of the 
     * Video class when deserialized by Spring's default 
     * Jackson library.
     * 
     * Returns the JSON representation of the Video object that
     * was stored along with any updates to that object made by the server.
     * @param video
     * @return
     * @throws IOException 
     */
    @RequestMapping(value = VIDEO_SVC_PATH, method = RequestMethod.POST)
    public @ResponseBody Video addVideo(@RequestBody Video v, HttpServletResponse response) throws IOException {

        try {
            save(v);
            v.setDataUrl(getDataUrl(v.getId()));
            return v;
        } catch (Throwable e) {
            response.sendError(404, ERROR_MSG);
            return v;
        }

    }

    /**
     * POST /video/{id}/data
     * Upload a video... after the user has created it
     * 
     * The binary mpeg data for the video should be provided in a multipart
     * request as a part with the key "data". The id in the path should be
     * replaced with the unique identifier generated by the server for the
     * Video
     * @param videoData
     * @return
     * @throws IOException 
     */
    @RequestMapping(value = VIDEO_DATA_PATH, method = RequestMethod.POST)
    public @ResponseBody VideoStatus addVideoData(@PathVariable(ID_PARAMETER) long id,
            final @RequestParam(DATA_PARAMETER) MultipartFile videoData, HttpServletResponse response)
            throws IOException {

        Video video;
        try {
            video = videos.get(id);
            saveSomeData(video, videoData);
        } catch (Throwable e) {
            response.sendError(404, ERROR_MSG);
        } finally {
            return new VideoStatus(VideoState.READY);
        }

    }

    /**
     * GET /video/{id}/data
     * 
     * Returns the binary mpeg data (if any) for the video with the given
     * identifier. If no mpeg data has been uploaded for the specified video,
     * then the server should return a 404 status code.
     * @param id
     * @return video
     * @throws IOException 
     */
    @RequestMapping(value = VIDEO_DATA_PATH, method = RequestMethod.GET)
    public void getData(@PathVariable("id") long id, HttpServletResponse response) throws IOException {

        //response.setContentType("video/mpeg");
        Video video = videos.get(id);

        try {
            serveSomeVideo(video, response);
        } catch (Throwable e) {
            //throw new FileNotFoundException();
            response.sendError(404, ERROR_MSG);
        }

    }

    ///////////////////////////////////// HELPERS //////////////////////////////////////////

    /**
     * Saving a video to the database
     */
    public Video save(Video v) {
        checkAndSetId(v);
        videos.put(v.getId(), v);
        return v;
    }

    /**
     * Helper method for when we save a video to the database...
     * Ensures that the video's id != 0 before setting it.
     */
    private void checkAndSetId(Video video) {
        if (video.getId() == 0) {
            video.setId(currentId.incrementAndGet());
        }
    }

    /**
     * Save some or part of a videos data when
     * we're initially uploading it from MultipartFile data
     * @throws IOException 
     */
    public void saveSomeData(Video video, MultipartFile videoData) throws IOException {

        mVideoFileManager = VideoFileManager.get();

        mVideoFileManager.saveVideoData(video, videoData.getInputStream());
    }

    /**
     * Serve video to the client through an HttpServletResponse
     * @param video
     * @param response
     * @throws IOException 
     */
    public void serveSomeVideo(Video video, HttpServletResponse response) throws IOException {
        response.setContentType(video.getContentType());
        mVideoFileManager = VideoFileManager.get();
        mVideoFileManager.copyVideoData(video, response.getOutputStream());
    }

    /**
     * Helper method for getting the url of a video based
     * on the attainment of an id
     */
    public String getDataUrl(Long videoId) {
        String dataUrl = getUrlBaseForLocalServer() + "/video/" + videoId.toString() + "/data";
        return dataUrl;
    }

    /**
     * Helps the helper method for getting the url of a video by
     * generating the urlbase for a local server
     */
    public String getUrlBaseForLocalServer() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        String base = "http://" + request.getServerName()
                + ((request.getServerPort() != 80) ? ":" + request.getServerPort() : "");
        return base;
    }

}