org.duracloud.duradmin.spaces.controller.SnapshotController.java Source code

Java tutorial

Introduction

Here is the source code for org.duracloud.duradmin.spaces.controller.SnapshotController.java

Source

/*
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 *     http://duracloud.org/license/
 */

package org.duracloud.duradmin.spaces.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.List;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;

import org.apache.http.HttpStatus;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.duracloud.client.ContentStore;
import org.duracloud.client.ContentStoreManager;
import org.duracloud.client.task.SnapshotTaskClient;
import org.duracloud.client.task.SnapshotTaskClientManager;
import org.duracloud.common.constant.Constants;
import org.duracloud.error.ContentStateException;
import org.duracloud.error.ContentStoreException;
import org.duracloud.security.DuracloudUserDetailsService;
import org.duracloud.snapshot.dto.SnapshotContentItem;
import org.duracloud.snapshot.dto.SnapshotHistoryItem;
import org.duracloud.snapshot.dto.task.CreateSnapshotTaskResult;
import org.duracloud.snapshot.dto.task.GetSnapshotContentsTaskResult;
import org.duracloud.snapshot.dto.task.GetSnapshotHistoryTaskResult;
import org.duracloud.snapshot.id.SnapshotIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
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.servlet.ModelAndView;

/**
 * @author Daniel Bernstein Date: Jan 27,2014
 */
@Controller
public class SnapshotController {

    protected final Logger log = LoggerFactory.getLogger(SnapshotController.class);

    private ContentStoreManager contentStoreManager;
    private DuracloudUserDetailsService userDetailsService;
    private SnapshotTaskClientManager snapshotTaskClientManager;

    @Autowired(required = true)
    public SnapshotController(@Qualifier("contentStoreManager") ContentStoreManager contentStoreManager,
            @Qualifier("userDetailsSvc") DuracloudUserDetailsService userDetailsService,
            SnapshotTaskClientManager snapshotTaskClientManager) {
        this.contentStoreManager = contentStoreManager;
        this.userDetailsService = userDetailsService;
        this.snapshotTaskClientManager = snapshotTaskClientManager;
    }

    @RequestMapping(value = "/spaces/snapshot", method = RequestMethod.POST)
    @ResponseBody
    public String create(HttpServletRequest request, HttpServletResponse response, @RequestParam String spaceId,
            @RequestParam String storeId, @RequestParam String description) throws Exception {

        ContentStore store = getContentStore(storeId);
        // check that a snapshot is not already being generated.
        response.setHeader("Content-Type", MediaType.APPLICATION_JSON);

        if (isSnapshotInProgress(store, spaceId)) {
            response.setStatus(HttpStatus.SC_METHOD_FAILURE);
            return "{\"result\":\"Snapshot already in progress.\"}";
        } else {

            String username = getUsername(request);
            String userEmail = getUserEmail(username);

            SnapshotTaskClient taskClient = getTaskClient(storeId);
            try {
                CreateSnapshotTaskResult result = taskClient.createSnapshot(spaceId, description, userEmail);
                response.setStatus(HttpStatus.SC_ACCEPTED);
                return result.serialize();

            } catch (ContentStateException ex) {
                response.setStatus(HttpStatus.SC_CONFLICT);
                return ex.getMessage();
            }
        }
    }

    protected String getUserEmail(String username) {
        String userEmail = userDetailsService.getUserByUsername(username).getEmail();
        return userEmail;
    }

    protected String getUsername(HttpServletRequest request) {
        String username = request.getUserPrincipal().getName();
        return username;
    }

    @RequestMapping(value = "/spaces/snapshot", method = RequestMethod.GET)
    public ModelAndView get(@RequestParam String storeId, @RequestParam String spaceId) {

        Properties props = new Properties();
        try {
            ContentStore store = this.contentStoreManager.getContentStore(storeId);
            if (store.contentExists(spaceId, Constants.SNAPSHOT_PROPS_FILENAME)) {
                try (InputStream is = store.getContent(spaceId, Constants.SNAPSHOT_PROPS_FILENAME).getStream()) {
                    props.load(is);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            props.put("error", "Snapshot properties could not be loaded: " + e.getMessage());
        }

        ModelAndView mav = new ModelAndView("jsonView");
        for (Object key : props.keySet()) {
            mav.addObject(key.toString(), props.get(key));
        }
        return mav;
    }

    @RequestMapping(value = "/spaces/snapshots/{storeId}", method = RequestMethod.GET)
    @ResponseBody
    public String getSnapshotList(@PathVariable("storeId") String storeId) {
        try {
            return getTaskClient(storeId).getSnapshots().serialize();
        } catch (ContentStoreException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @RequestMapping(value = "/spaces/snapshots/{storeId}/{snapshotId:.+}", method = RequestMethod.GET)
    @ResponseBody
    public String getSnapshot(@PathVariable("storeId") String storeId,
            @PathVariable("snapshotId") String snapshotId) throws Exception {

        return getTaskClient(storeId).getSnapshot(snapshotId).serialize();
    }

    @RequestMapping(value = "/spaces/snapshots/{storeId}/{snapshotId}/history", method = RequestMethod.GET)
    public ModelAndView getHistory(@PathVariable("storeId") String storeId,
            @PathVariable("snapshotId") String snapshotId,
            @RequestParam(value = "page", required = false) Integer page,
            @RequestParam(value = "attachment", required = false, defaultValue = "false") Boolean attachment,
            HttpServletResponse response) {
        try {
            SnapshotTaskClient taskClient = getTaskClient(storeId);

            if (attachment) {
                StringBuffer contentDisposition = new StringBuffer();
                contentDisposition.append("attachment;");
                contentDisposition.append("filename=\"");
                contentDisposition.append(snapshotId + ".history.json");
                contentDisposition.append("\"");
                response.setHeader("Content-Disposition", contentDisposition.toString());
            }

            if (page == null) {
                page = 0;
            }

            streamSnapshotHistory(page, storeId, snapshotId, taskClient, response);
            return null;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    private void streamSnapshotHistory(int page, String storeId, String snapshotId, SnapshotTaskClient taskClient,
            HttpServletResponse response) throws IOException, ContentStoreException {
        PrintWriter writer = response.getWriter();

        int pageSize = 200;
        if (page < 0) {
            pageSize = 1000;
        }

        int pageCounter = page;

        JsonFactory factory = new JsonFactory();
        JsonGenerator jwriter = factory.createJsonGenerator(writer);
        jwriter.writeStartObject();

        jwriter.writeFieldName("historyItems");
        jwriter.writeStartArray();
        GetSnapshotHistoryTaskResult result = null;
        while (true) {
            result = getSnapshotHistory(snapshotId, pageCounter, taskClient, pageSize);
            List<SnapshotHistoryItem> items = result.getHistoryItems();
            for (SnapshotHistoryItem item : items) {
                jwriter.writeStartObject();
                jwriter.writeNumberField("historyDate", item.getHistoryDate().getTime());
                jwriter.writeStringField("history", item.getHistory());
                jwriter.writeEndObject();
            }

            if (items.size() < pageSize || page >= 0) {
                break;
            } else {
                pageCounter++;
            }
        }

        jwriter.writeEndArray();
        if (page >= 0) {
            jwriter.writeNumberField("page", page);
            jwriter.writeNumberField("totalCount", result.getTotalCount());

            if (result.getHistoryItems().size() == pageSize && (page + 1 * pageSize < result.getTotalCount())) {
                jwriter.writeNumberField("nextPage", page + 1);
            } else {
                jwriter.writeNullField("nextPage");
            }
        }

        jwriter.writeStringField("snapshotId", snapshotId);
        jwriter.writeStringField("storeId", storeId);
        jwriter.writeEndObject();
        jwriter.close();
    }

    protected GetSnapshotHistoryTaskResult getSnapshotHistory(String snapshotId, Integer page,
            SnapshotTaskClient taskClient, int pageSize) throws ContentStoreException {
        GetSnapshotHistoryTaskResult result = taskClient.getSnapshotHistory(snapshotId, page, pageSize);
        List<SnapshotHistoryItem> items = result.getHistoryItems();
        // Replace single quotes with double quotes in history values.
        // This allows history values that are valid JSON (without escaping) to be
        // provided as snapshot history updates, and be displayed properly.
        for (SnapshotHistoryItem item : items) {
            item.setHistory(item.getHistory().replaceAll("'", "\""));
        }
        return result;
    }

    @RequestMapping(value = "/spaces/snapshots/{storeId}/{snapshotId}/content", method = RequestMethod.GET)
    public ModelAndView getContent(@PathVariable("storeId") String storeId,
            @PathVariable("snapshotId") String snapshotId,
            @RequestParam(value = "page", required = false) Integer page,
            @RequestParam(value = "prefix", required = false) String prefix) {
        try {
            SnapshotTaskClient taskClient = getTaskClient(storeId);

            if (page == null) {
                page = 0;
            }
            int pageSize = 200;
            GetSnapshotContentsTaskResult result = taskClient.getSnapshotContents(snapshotId, page, pageSize,
                    prefix);
            List<SnapshotContentItem> items = result.getContentItems();
            ModelAndView mav = new ModelAndView("jsonView");
            mav.addObject("contents", items);
            mav.addObject("page", page);
            mav.addObject("snapshotId", snapshotId);
            mav.addObject("storeId", storeId);
            mav.addObject("nextPage", items.size() == pageSize ? page + 1 : null);
            mav.addObject("prefix", prefix);
            mav.addObject("totalCount", result.getTotalCount());
            return mav;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the name of the restore space, if it exists, associated with a snapshot
     *
     * @param request
     * @param snapshotId
     * @return
     * @throws ParseException
     */
    @RequestMapping(value = "/spaces/snapshots/{storeId}/{snapshotId}/restore-space-id", method = RequestMethod.GET)
    @ResponseBody
    public String restoreSpaceId(HttpServletRequest request, @PathVariable("storeId") String storeId,
            @PathVariable("snapshotId") String snapshotId) throws Exception {
        ContentStore contentStore = getContentStore(storeId);

        String spaceId = SnapshotIdentifier.parseSnapshotId(snapshotId).getRestoreSpaceId();

        if (contentStore.spaceExists(spaceId)) {
            return "{ \"spaceId\": \"" + spaceId + "\"," + "\"storeId\": \"" + storeId + "\"}";
        } else {
            return "{}";
        }
    }

    protected SnapshotTaskClient getTaskClient(String storeId) throws ContentStoreException {
        SnapshotTaskClient taskClient = this.snapshotTaskClientManager.get(storeId);
        return taskClient;
    }

    @RequestMapping(value = "/spaces/restores/{storeId}/by-snapshot/{snapshotId:.+}", method = RequestMethod.GET)
    @ResponseBody
    public String getRestore(@PathVariable("storeId") String storeId,
            @PathVariable("snapshotId") String snapshotId) {
        try {
            return getTaskClient(storeId).getRestoreBySnapshot(snapshotId).serialize();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @RequestMapping(value = "/spaces/restores/{storeId}/{restoreId:.+}", method = RequestMethod.GET)
    @ResponseBody
    public String getRestoreByRestoreId(@PathVariable("storeId") String storeId,
            @PathVariable("restoreId") String restoreId) {
        try {
            return getTaskClient(storeId).getRestore(restoreId).serialize();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @RequestMapping(value = "/spaces/restores", method = RequestMethod.POST)
    @ResponseBody
    public String restore(HttpServletRequest request, @RequestParam String storeId, @RequestParam String snapshotId)
            throws Exception {
        try {
            String userEmail = getUserEmail(getUsername(request));
            return getTaskClient(storeId).restoreSnapshot(snapshotId, userEmail).serialize();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }

    }

    @RequestMapping(value = "/spaces/restores/request", method = RequestMethod.POST)
    @ResponseBody
    public String requestRestore(HttpServletRequest request, @RequestParam String storeId,
            @RequestParam String snapshotId) throws Exception {
        try {
            String userEmail = getUserEmail(getUsername(request));
            return getTaskClient(storeId).requestRestoreSnapshot(snapshotId, userEmail).serialize();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }

    }

    private boolean isSnapshotInProgress(ContentStore store, String spaceId) {
        try {
            return store.getSpaceProperties(spaceId).containsKey(Constants.SNAPSHOT_ID_PROP);
        } catch (ContentStoreException ex) {
            throw new RuntimeException(ex);
        }
    }

    private ContentStore getContentStore(String storeId) throws ContentStoreException {
        return this.contentStoreManager.getContentStore(storeId);
    }

}