FormResourceEdit.java 13.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.servlet.RequestDispatcher
 *  javax.servlet.ServletException
 *  javax.servlet.ServletRequest
 *  javax.servlet.ServletResponse
 *  org.apache.commons.collections.CollectionUtils
 *  org.apache.jackrabbit.util.Text
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.request.RequestDispatcherOptions
 *  org.apache.sling.api.request.RequestParameter
 *  org.apache.sling.api.request.RequestParameterMap
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.foundation.forms;

import com.day.cq.wcm.foundation.forms.MergedMultiResource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestDispatcherOptions;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.request.RequestParameterMap;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class FormResourceEdit {
    private static final Logger log = LoggerFactory.getLogger(FormResourceEdit.class);
    public static final String RESOURCES_ATTRIBUTE = "cq.form.editresources";
    public static final String RESOURCES_PARAM = ":resource";
    public static final String REOPEN_PARAM = "reopen";
    public static final String WRITE_SUFFIX = "@Write";

    public static void setResources(ServletRequest req, List<Resource> resources) {
        req.setAttribute("cq.form.editresources", resources);
    }

    public static List<Resource> getResources(ServletRequest req) {
        return (List)req.getAttribute("cq.form.editresources");
    }

    public static Resource getMergedResource(List<Resource> resources) {
        return new MergedMultiResource(resources);
    }

    public static CommonAndPartial getCommonAndPartialMultiValues(List<Resource> resources, String name) {
        CommonAndPartial r = new CommonAndPartial();
        boolean firstResource = true;
        for (Resource resource : resources) {
            ValueMap map = (ValueMap)resource.adaptTo(ValueMap.class);
            if (map == null) continue;
            String[] values = (String[])map.get(name, (Object)new String[0]);
            if (firstResource) {
                for (String v : values) {
                    r.common.add(v);
                }
                firstResource = false;
                continue;
            }
            List<String> newValues = Arrays.asList(values);
            r.partial.addAll(CollectionUtils.disjunction(r.common, newValues));
            r.common = new HashSet<String>(CollectionUtils.intersection(r.common, newValues));
        }
        return r;
    }

    public static boolean isSingleResource(ServletRequest req) {
        List<Resource> r = FormResourceEdit.getResources(req);
        return r != null && r.size() == 1;
    }

    public static boolean isMultiResource(ServletRequest req) {
        List<Resource> r = FormResourceEdit.getResources(req);
        return r != null && r.size() > 1;
    }

    public static boolean isSingleResourcePost(SlingHttpServletRequest request) {
        RequestParameter[] resourceParams = request.getRequestParameters(":resource");
        return resourceParams == null || resourceParams.length == 1;
    }

    public static boolean isMultiResourcePost(SlingHttpServletRequest request) {
        RequestParameter[] resourceParams = request.getRequestParameters(":resource");
        return resourceParams != null && resourceParams.length > 1;
    }

    public static String getPostResourcePath(SlingHttpServletRequest request) {
        RequestParameter[] resourceParams = request.getRequestParameters(":resource");
        if (resourceParams != null && resourceParams.length == 1) {
            return resourceParams[0].getString();
        }
        return null;
    }

    public static List<Resource> getPostResources(SlingHttpServletRequest request) {
        ResourceResolver resolver = request.getResourceResolver();
        RequestParameter[] resourceParams = request.getRequestParameters(":resource");
        Session session = (Session)request.getResourceResolver().adaptTo(Session.class);
        ArrayList<Resource> resources = new ArrayList<Resource>();
        if (resourceParams != null) {
            for (RequestParameter rp : resourceParams) {
                Resource r = resolver.getResource(rp.getString());
                try {
                    if (r == null || !session.hasPermission(r.getPath(), "set_property")) continue;
                    resources.add(r);
                    continue;
                }
                catch (RepositoryException e) {
                    log.error("Could not check write permission on node", (Throwable)e);
                }
            }
        }
        return resources;
    }

    public static void multiPost(List<Resource> resources, SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        RequestParameterMap originalParams = request.getRequestParameterMap();
        TreeMap groupedParams = new TreeMap();
        boolean requireItemPrefix = false;
        HashSet<String> paramsToKeep = new HashSet<String>();
        HashSet<String> paramsToRemove = new HashSet<String>();
        for (Map.Entry param : originalParams.entrySet()) {
            String op;
            TreeMap map;
            int pos;
            String propName;
            String name = (String)param.getKey();
            if (":operation".equals(name) && !"modify".equals(op = originalParams.getValue(name).getString())) {
                throw new ServletException("Only :operation=modify can be used when posting to multiple resources (was: '" + op + "')");
            }
            if (name.startsWith("./")) {
                requireItemPrefix = true;
            }
            if ((map = (TreeMap)groupedParams.get(propName = (pos = name.indexOf("@")) >= 0 ? name.substring(0, pos) : name)) == null) {
                map = new TreeMap();
                groupedParams.put(propName, map);
            }
            map.put(name, param.getValue());
            if (name.endsWith("@Write")) {
                paramsToKeep.add(propName);
                map.remove(name);
            }
            if (":formid".equals(name) || ":formstart".equals(name) || ":resource".equals(name)) continue;
            if (name.startsWith(":")) {
                paramsToKeep.add(name);
            }
            if (!name.endsWith("@MoveFrom")) continue;
            paramsToRemove.add(propName);
        }
        Iterator iter = groupedParams.keySet().iterator();
        while (iter.hasNext()) {
            String name = (String)iter.next();
            if (paramsToKeep.contains(name) && !paramsToRemove.contains(name)) continue;
            iter.remove();
        }
        ParameterMap params = new ParameterMap();
        log.debug("posting to multiple resources:");
        boolean first = true;
        for (Resource r : resources) {
            String path = r.getPath();
            log.debug("{}", (Object)path);
            for (Map p : groupedParams.values()) {
                for (Map.Entry param2 : p.entrySet()) {
                    String name = (String)param2.getKey();
                    if (name.startsWith(":") || name.startsWith("/")) {
                        if (!first) continue;
                        params.put(name, param2.getValue());
                        continue;
                    }
                    if (requireItemPrefix) {
                        if (name.startsWith("./")) {
                            params.put(path + "/" + name.substring("./".length()), param2.getValue());
                            continue;
                        }
                        if (!name.startsWith("../")) continue;
                        path = Text.getRelativeParent((String)path, (int)1);
                        params.put(path + "/" + name.substring("../".length()), param2.getValue());
                        continue;
                    }
                    params.put(path + "/" + name, param2.getValue());
                }
            }
            first = false;
        }
        if (log.isDebugEnabled()) {
            log.debug("rewritten parameters:");
            FormResourceEdit.logParams(params);
        }
        RequestDispatcherOptions options = new RequestDispatcherOptions();
        options.setReplaceSelectors("");
        options.setReplaceSuffix("");
        RequestDispatcher dispatcher = request.getRequestDispatcher(request.getResource(), options);
        dispatcher.forward((ServletRequest)new CustomParameterRequest(request, params), (ServletResponse)response);
    }

    private static void logParams(Map<String, RequestParameter[]> parameters) {
        for (Map.Entry<String, RequestParameter[]> ps : parameters.entrySet()) {
            for (RequestParameter rp : ps.getValue()) {
                log.debug("{} = {}", (Object)ps.getKey(), (Object)rp.getString());
            }
        }
    }

    private static class ParameterMap
    extends TreeMap<String, RequestParameter[]>
    implements RequestParameterMap {
        private static final long serialVersionUID = 4554110574522792609L;
        private Map<String, String[]> stringParameterMap;

        private ParameterMap() {
        }

        public RequestParameter[] getValues(String name) {
            return (RequestParameter[])this.get(name);
        }

        public RequestParameter getValue(String name) {
            RequestParameter[] params = (RequestParameter[])this.get(name);
            return params != null && params.length > 0 ? params[0] : null;
        }

        public String getStringValue(String name) {
            RequestParameter param = this.getValue(name);
            return param != null ? param.getString() : null;
        }

        public String[] getStringValues(String name) {
            return ParameterMap.toStringArray(this.getValues(name));
        }

        public Map<String, String[]> getStringParameterMap() {
            if (this.stringParameterMap == null) {
                LinkedHashMap pm = new LinkedHashMap();
                for (Map.Entry ppmEntry : this.entrySet()) {
                    pm.put(ppmEntry.getKey(), ParameterMap.toStringArray((RequestParameter[])ppmEntry.getValue()));
                }
                this.stringParameterMap = Collections.unmodifiableMap(pm);
            }
            return this.stringParameterMap;
        }

        private static String[] toStringArray(RequestParameter[] params) {
            if (params == null) {
                return null;
            }
            String[] ps = new String[params.length];
            for (int i = 0; i < params.length; ++i) {
                ps[i] = params[i].getString();
            }
            return ps;
        }
    }

    private static class CustomParameterRequest
    extends SlingHttpServletRequestWrapper {
        private ParameterMap parameters;

        public CustomParameterRequest(SlingHttpServletRequest request, ParameterMap params) {
            super(request);
            this.parameters = params;
        }

        public RequestParameter getRequestParameter(String name) {
            return this.parameters.getValue(name);
        }

        public RequestParameterMap getRequestParameterMap() {
            return this.parameters;
        }

        public RequestParameter[] getRequestParameters(String name) {
            return this.parameters.getValues(name);
        }

        public String getParameter(String name) {
            return this.parameters.getStringValue(name);
        }

        public Map getParameterMap() {
            return this.parameters.getStringParameterMap();
        }

        public Enumeration getParameterNames() {
            return Collections.enumeration(this.parameters.keySet());
        }

        public String[] getParameterValues(String name) {
            return this.parameters.getStringValues(name);
        }
    }

    public static class CommonAndPartial {
        public Set<String> common = new HashSet<String>();
        public Set<String> partial = new HashSet<String>();
    }

}