BinaryValueServlet.java 9.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.AccessDeniedException
 *  javax.servlet.ServletException
 *  javax.servlet.http.HttpServletResponse
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.servlets.HtmlResponse
 *  org.apache.sling.api.servlets.SlingAllMethodsServlet
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.undo.impl;

import com.day.cq.wcm.undo.BinaryHandlingException;
import com.day.cq.wcm.undo.BinaryValueManager;
import java.io.IOException;
import javax.jcr.AccessDeniedException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HtmlResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=0)
@Service
@Properties(value={@Property(name="sling.servlet.paths", value={"/libs/wcm/undo/bvm"}), @Property(name="sling.servlet.methods", value={"POST"})})
public class BinaryValueServlet
extends SlingAllMethodsServlet {
    private static final String PRM_OPERATION = "operation";
    private static final String PRM_PARAGRAPH = "par";
    private static final String PRM_SRC_PATH = "srcPath";
    private static final String PRM_TARGET_PATH = "targetPath";
    private static final String PRM_GLOBAL = "global";
    private static final String PRM_ORIGINAL_REF = "originalBlob";
    private static final String PRM_DELETE_PATHS = "deletePaths";
    private static final String PRMVAL_SAVE = "save";
    private static final String PRMVAL_RESTORE = "restore";
    private static final String PRMVAL_DELETE = "delete";
    private static final String PRMVAL_TRUE = "true";
    @Reference
    private BinaryValueManager binaryValueManager;
    private static final Logger log = LoggerFactory.getLogger(BinaryValueServlet.class);

    protected void doPost(SlingHttpServletRequest req, SlingHttpServletResponse resp) throws ServletException, IOException {
        String op = req.getParameter("operation");
        if (op == null) {
            throw new ServletException("Missing operation.");
        }
        if (!("save".equals(op) || "restore".equals(op) || "delete".equals(op))) {
            throw new ServletException("Invalid operation: " + op);
        }
        String parPath = req.getParameter("par");
        if (parPath == null && !"delete".equals(op)) {
            throw new ServletException("Missing paragraph.");
        }
        String srcPath = req.getParameter("srcPath");
        if (srcPath == null && !"delete".equals(op)) {
            throw new ServletException("Missing source path.");
        }
        if (srcPath != null && srcPath.length() == 0) {
            srcPath = null;
        }
        if (srcPath == null && "save".equals(op)) {
            throw new ServletException("Invalid source path for save operation.");
        }
        String targetPath = null;
        boolean isGlobalRestore = false;
        if ("restore".equals(op)) {
            targetPath = req.getParameter("targetPath");
            if (targetPath == null) {
                throw new ServletException("Missing target path for restore operation.");
            }
            String globalParam = req.getParameter("global");
            if (globalParam != null) {
                isGlobalRestore = globalParam.equals("true");
            }
        }
        String originalRef = req.getParameter("originalBlob");
        String[] deletePaths = req.getParameterValues("deletePaths");
        if ("delete".equals(op) && (deletePaths == null || deletePaths.length == 0)) {
            throw new ServletException("Missing paths for delete operation.");
        }
        ResourceResolver resolver = req.getResource().getResourceResolver();
        Resource par = parPath != null ? resolver.getResource(parPath) : null;
        String path = "";
        HtmlResponse htmlPage = new HtmlResponse();
        try {
            if ("save".equals(op)) {
                boolean isSaveable = true;
                if (originalRef != null) {
                    isSaveable = this.binaryValueManager.isChanged(par, srcPath, originalRef);
                }
                if (isSaveable) {
                    String id = this.binaryValueManager.save(par, srcPath);
                    path = parPath;
                    if (id != null) {
                        htmlPage.setTitle("Binary undo value saved.");
                        htmlPage.setPath(id);
                        htmlPage.onCreated(id);
                        htmlPage.setCreateRequest(true);
                    } else {
                        htmlPage.setTitle("Skipped removed binary undo value.");
                        htmlPage.setPath("");
                        htmlPage.onDeleted("");
                        htmlPage.setCreateRequest(false);
                    }
                } else {
                    log.debug("Binary at '{}/{}' has not been changed, removing original data", (Object)par.getPath(), (Object)srcPath);
                    this.binaryValueManager.delete(resolver, originalRef);
                    htmlPage.setTitle("Binary undo value remains unchanged.");
                    htmlPage.setPath(originalRef);
                    htmlPage.onDeleted(originalRef);
                    htmlPage.setCreateRequest(false);
                }
            } else if ("restore".equals(op)) {
                path = targetPath;
                htmlPage.setPath("");
                if (srcPath != null) {
                    Resource undoData = resolver.getResource(srcPath);
                    this.binaryValueManager.restore(undoData, par, targetPath);
                    htmlPage.onModified(targetPath);
                    htmlPage.setTitle("Binary undo value restored.");
                    htmlPage.setPath("");
                    htmlPage.setCreateRequest(false);
                } else {
                    this.binaryValueManager.delete(par, targetPath, !isGlobalRestore);
                    htmlPage.onDeleted(targetPath);
                    htmlPage.setTitle("Binary undo value removed.");
                    htmlPage.setPath("");
                    htmlPage.setCreateRequest(false);
                }
            } else if ("delete".equals(op)) {
                for (String pathToDelete : deletePaths) {
                    this.binaryValueManager.delete(resolver, pathToDelete);
                    htmlPage.onDeleted(pathToDelete);
                }
                htmlPage.setTitle("Binary undo values removed.");
                htmlPage.setPath("");
                htmlPage.setCreateRequest(false);
            }
            htmlPage.setLocation(path);
            int pathSepPos = path.lastIndexOf("/");
            String parentLoc = pathSepPos >= 0 ? path.substring(0, pathSepPos) : "";
            htmlPage.setParentLocation(parentLoc);
        }
        catch (BinaryHandlingException bhe) {
            if (par == null && parPath != null) {
                log.info("Could not retrieve paragraph '{}'. It may have been deleted due to a concurrent (delete or move) operation.", (Object)parPath);
            } else if (bhe.getCause() instanceof AccessDeniedException) {
                log.info("Cannot save binary data for undo. Please ensure that all users that are eligible for undo have write permissions on the directory that is configured for saving undo data. Note that improper configuration may impose a security risk.");
            } else {
                log.error("Could not execute binary value operation: " + op, (Throwable)bhe);
            }
            htmlPage.setTitle("save".equals(op) ? "Could not save undo data." : "Could not restore undo data.");
            htmlPage.setError((Throwable)bhe);
        }
        catch (Exception e) {
            htmlPage.setTitle("Internal error.");
            htmlPage.setError((Throwable)e);
            log.error("Internal error while executing operation '" + op + "'", (Throwable)e);
        }
        htmlPage.send((HttpServletResponse)resp, true);
    }

    protected void bindBinaryValueManager(BinaryValueManager binaryValueManager) {
        this.binaryValueManager = binaryValueManager;
    }

    protected void unbindBinaryValueManager(BinaryValueManager binaryValueManager) {
        if (this.binaryValueManager == binaryValueManager) {
            this.binaryValueManager = null;
        }
    }
}