ch.silviowangler.dox.web.DocumentController.java Source code

Java tutorial

Introduction

Here is the source code for ch.silviowangler.dox.web.DocumentController.java

Source

/*
 * Copyright 2012 - 2013 Silvio Wangler (silvio.wangler@gmail.com)
 *
 * 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 ch.silviowangler.dox.web;

import ch.silviowangler.dox.api.*;
import ch.silviowangler.dox.api.stats.StatisticsService;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.Version;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.SortedSet;

import static eu.bitwalker.useragentutils.Browser.*;
import static java.lang.Integer.valueOf;
import static javax.servlet.http.HttpServletResponse.*;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

/**
 * @author Silvio Wangler
 * @since 0.1
 * <div>
 * Date: 22.07.12 11:45
 * </div>
 */
@Controller
public class DocumentController {

    @Autowired
    private DocumentService documentService;
    @Autowired
    private StatisticsService statisticsService;
    @Value("#{systemEnvironment['DOX_STORE']}")
    private File archiveDirectory;

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @RequestMapping(method = GET, value = "/document/{hash}.thumbnail")
    public void getDocument(@PathVariable("hash") String hash, HttpServletResponse response,
            @RequestHeader("User-Agent") String userAgent) {

        File thumbnailsDir = new File(this.archiveDirectory, "thumbnails");

        final Browser browser = parseUserAgentString(userAgent);

        File webp = new File(thumbnailsDir, hash + ".webp");
        File jpg = new File(thumbnailsDir, hash + ".jpg");

        if (isWebpSupportedBrowser(userAgent, browser) && webp.exists()) {
            response.setStatus(SC_OK);
            response.addHeader("Content-Type", "image/webp");
            response.addHeader("Content-Disposition", "inline; filename=\"" + webp.getName() + "\"");

            try {
                IOUtils.copy(new FileInputStream(webp), response.getOutputStream());
                response.getOutputStream().flush();
            } catch (IOException e) {
                logger.error("Unable to write thumbnail for hash {} to output stream", hash, e);
            }
        } else if (jpg.exists()) {
            response.setStatus(SC_OK);
            response.addHeader("Content-Type", "image/jpeg");
            response.addHeader("Content-Disposition", "inline; filename=\"" + jpg.getName() + "\"");

            try {
                IOUtils.copy(new FileInputStream(jpg), response.getOutputStream());
                response.getOutputStream().flush();
            } catch (IOException e) {
                logger.error("Unable to write thumbnail for hash {} to output stream", hash, e);
            }
        } else {
            response.setStatus(SC_NOT_FOUND);
        }
    }

    private boolean isWebpSupportedBrowser(String userAgent, Browser browser) {
        return isChromeWithWebpSupport(userAgent, browser) || isOperaWithWebpSupport(userAgent, browser);
    }

    private boolean isChromeWithWebpSupport(String userAgent, Browser browser) {
        return browser.getGroup() == CHROME && valueOf(browser.getVersion(userAgent).getMajorVersion()) >= 9;
    }

    private boolean isOperaWithWebpSupport(String userAgent, Browser browser) {
        final Version version = browser.getVersion(userAgent);
        return browser.getGroup() == OPERA && valueOf(version.getMajorVersion()) >= 11;
    }

    @RequestMapping(method = GET, value = "/document/{id}")
    public void getDocument(@PathVariable("id") Long id, HttpServletResponse response) {
        try {
            PhysicalDocument document = documentService.findPhysicalDocument(id);

            final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String username = (authentication != null) ? ((User) authentication.getPrincipal()).getUsername()
                    : "anonymous";
            statisticsService.registerDocumentReferenceClick(String.valueOf(id), username);

            response.setStatus(SC_OK);
            response.addHeader("Content-Type", document.getMimeType());
            response.addHeader("Content-Disposition", "inline; filename=\"" + document.getFileName() + "\"");
            response.getOutputStream().write(document.getContent());
            response.getOutputStream().flush();
        } catch (DocumentNotFoundException | DocumentNotInStoreException e) {
            logger.warn("Document with id '{}' not found", id, e);
            response.setStatus(SC_NOT_FOUND);
        } catch (AccessDeniedException ade) {
            logger.warn("Access denied on document {}", id, ade);
            response.setStatus(SC_FORBIDDEN);
        } catch (IOException e) {
            logger.error("Could not write document to output stream", e);
            response.setStatus(SC_INTERNAL_SERVER_ERROR);
        }
    }

    @RequestMapping(method = GET, value = "/document/edit/{id}")
    public ModelAndView editDocument(@PathVariable("id") Long id) {

        ModelAndView modelAndView = new ModelAndView("edit.doc", new HashMap<String, Object>());

        try {
            final DocumentReference documentReference = documentService.findDocumentReference(id);
            final SortedSet<Attribute> attributes = documentService
                    .findAttributes(documentReference.getDocumentClass());

            modelAndView.getModel().put("doc", documentReference);
            modelAndView.getModel().put("attributes", attributes);

        } catch (DocumentNotFoundException | DocumentClassNotFoundException e) {
            logger.error("No such document", e);
        }
        return modelAndView;
    }

    @RequestMapping(method = POST, value = "/document/edit/{id}")
    public ModelAndView editDocument(@PathVariable("id") Long id, HttpServletRequest request) {

        ModelAndView modelAndView = new ModelAndView("import.successful");

        try {
            DocumentReference documentReference = documentService.findDocumentReference(id);

            boolean didChangeValue = false;
            for (TranslatableKey key : documentReference.getIndices().keySet()) {
                final String paramValue = request.getParameter(key.getKey());

                if (paramValue != null) {
                    didChangeValue = true;
                    documentReference.getIndices().put(key,
                            new DescriptiveIndex(new String(paramValue.getBytes("iso-8859-1"), "utf-8")));
                }
            }

            if (didChangeValue) {
                documentReference = documentService.updateIndices(documentReference);
            }
            modelAndView.getModel().put("doc", documentReference);

        } catch (DocumentNotFoundException | UnsupportedEncodingException e) {
            modelAndView.setViewName("modification.doc.failed");
            logger.error("Cannot update document", e);
        }
        return modelAndView;
    }

    @RequestMapping(method = GET, value = "/document/delete/{id}")
    public ModelAndView deleteDocument(@PathVariable("id") Long id) {
        documentService.deleteDocument(id);

        return new ModelAndView("redirect:/");
    }
}