ParagraphList.java 12.4 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.xss.XSSAPI
 *  com.day.cq.commons.feed.StringResponseWrapper
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.api.components.Component
 *  com.day.cq.wcm.commons.WCMUtils
 *  javax.servlet.RequestDispatcher
 *  javax.servlet.Servlet
 *  javax.servlet.ServletException
 *  javax.servlet.ServletOutputStream
 *  javax.servlet.ServletRequest
 *  javax.servlet.ServletResponse
 *  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.request.RequestDispatcherOptions
 *  org.apache.sling.api.request.RequestPathInfo
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.servlets.SlingSafeMethodsServlet
 *  org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper
 *  org.apache.sling.commons.json.JSONArray
 *  org.apache.sling.commons.json.JSONException
 *  org.apache.sling.commons.json.JSONObject
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.foundation;

import com.adobe.granite.xss.XSSAPI;
import com.day.cq.commons.feed.StringResponseWrapper;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.commons.WCMUtils;
import com.day.cq.wcm.foundation.Paragraph;
import com.day.cq.wcm.foundation.ParagraphSystem;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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.request.RequestDispatcherOptions;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=0)
@Service(value={Servlet.class})
@Properties(value={@Property(name="sling.servlet.paths", value={"/bin/wcm/foundation/paragraphlist"}), @Property(name="sling.servlet.extensions", value={"html", "json"}), @Property(name="sling.servlet.methods", value={"GET"})})
public class ParagraphList
extends SlingSafeMethodsServlet {
    private final Logger log;
    @Reference
    private XSSAPI xssAPI;
    private static final long serialVersionUID = 2156140435583248698L;
    private static final String DEFAULT_START_PATH = "/content";
    public static final String QUERY = "query";
    public static final String LIMIT = "limit";
    public static final String START = "start";
    public static final int DEFAULT_LIMIT = 20;

    public ParagraphList() {
        this.log = LoggerFactory.getLogger((String)this.getClass().getName());
    }

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        Page page = null;
        Object resourceType = null;
        String queryString = request.getParameter("query");
        if (queryString == null || queryString.length() == 0) {
            queryString = "";
        }
        queryString = queryString.trim();
        String[] queryTerms = queryString.split("\\s+");
        RequestPathInfo pathInfo = request.getRequestPathInfo();
        String paramPath = queryString.replace("path:", "");
        String path = pathInfo.getSuffix() != null ? pathInfo.getSuffix() : (paramPath != null ? paramPath : "/content");
        try {
            page = (Page)request.getResourceResolver().getResource(path).adaptTo(Page.class);
        }
        catch (Exception e) {
            this.log.error("Specified path is not a page.", (Throwable)e);
        }
        if (page != null) {
            Resource content = page.getContentResource();
            ArrayList<String> resourceTypes = new ArrayList<String>();
            for (int t = 0; t < queryTerms.length; ++t) {
                String term = queryTerms[t].replace("\"", "");
                if (!term.startsWith("sling:resourceType:")) continue;
                resourceTypes.add(term.replace("sling:resourceType:", ""));
            }
            if (content != null) {
                List<Map> paragraphs = this.getResults(content, request, response);
                Iterator<Map> paraIt = paragraphs.iterator();
                while (paraIt.hasNext()) {
                    String paraPath = (String)paraIt.next().get("path");
                    Resource res = request.getResourceResolver().getResource(paraPath);
                    if (res == null || resourceTypes.size() <= 0) continue;
                    boolean isFiltered = false;
                    for (String rt : resourceTypes) {
                        if (rt == null || !res.isResourceType(rt)) continue;
                        isFiltered = true;
                        break;
                    }
                    if (isFiltered) continue;
                    paraIt.remove();
                }
                String startStr = request.getParameter("start");
                String limitStr = request.getParameter("limit");
                int start = startStr != null ? Math.max(Integer.parseInt(startStr), 0) : 0;
                int limit = limitStr != null ? Math.max(Integer.parseInt(limitStr), 0) : 20;
                int end = start + limit;
                if (start < paragraphs.size()) {
                    paragraphs = paragraphs.subList(start, end > paragraphs.size() ? paragraphs.size() : end);
                } else {
                    paragraphs.clear();
                }
                if ("json".equals(request.getRequestPathInfo().getExtension())) {
                    JSONObject jsonResults = new JSONObject();
                    try {
                        response.setContentType("application/json");
                        response.setCharacterEncoding("utf-8");
                        jsonResults = this.generateJsonOutput(paragraphs);
                    }
                    catch (JSONException e) {
                        throw new ServletException("Failed to produce JSON output", (Throwable)e);
                    }
                    finally {
                        response.getWriter().write(jsonResults.toString());
                    }
                }
                try {
                    response.getWriter().write(this.generateHtmlOutput(paragraphs, request, response));
                }
                catch (Exception e) {
                    throw new ServletException("Failed to produce HTML output", (Throwable)e);
                }
            }
        }
    }

    void writeEmptyJSON(SlingHttpServletResponse response) throws ServletException, IOException {
    }

    protected List<Map> getResults(Resource content, SlingHttpServletRequest request, SlingHttpServletResponse response) {
        ArrayList<Map> results = new ArrayList<Map>();
        Iterator iterator = content.getResourceResolver().listChildren(content);
        while (iterator.hasNext()) {
            Resource resource = (Resource)iterator.next();
            com.day.cq.wcm.api.components.Component component = WCMUtils.getComponent((Resource)resource);
            if (component == null || !component.isContainer()) continue;
            ParagraphSystem system = new ParagraphSystem(resource);
            for (Paragraph paragraph : system.paragraphs()) {
                if (paragraph.getType() != Paragraph.Type.NORMAL) continue;
                LinkedHashMap<String, String> result = new LinkedHashMap<String, String>();
                result.put("path", paragraph.getPath());
                String excerpt = this.render(paragraph.getPath(), request, response);
                result.put("excerpt", excerpt);
                results.add(result);
            }
        }
        return results;
    }

    protected String render(String path, SlingHttpServletRequest request, SlingHttpServletResponse response) {
        try {
            final StringWriter buffer = new StringWriter();
            final ServletOutputStream stream = new ServletOutputStream(){

                public void write(int b) throws IOException {
                    buffer.append((char)b);
                }
            };
            SlingHttpServletResponseWrapper wrapper = new SlingHttpServletResponseWrapper(response){

                public ServletOutputStream getOutputStream() {
                    return stream;
                }

                public PrintWriter getWriter() throws IOException {
                    return new PrintWriter(buffer);
                }

                public SlingHttpServletResponse getSlingResponse() {
                    return super.getSlingResponse();
                }
            };
            RequestDispatcher dispatcher = request.getRequestDispatcher(path + ".html");
            dispatcher.include((ServletRequest)request, (ServletResponse)wrapper);
            return buffer.toString();
        }
        catch (Exception e) {
            this.log.error("Exception occured: " + e.getMessage(), (Throwable)e);
            return e.getMessage();
        }
    }

    protected JSONObject generateJsonOutput(List<Map> paragraphs) throws JSONException {
        JSONArray hits = new JSONArray();
        for (Map paragraph : paragraphs) {
            JSONObject hit = new JSONObject();
            for (String key : paragraph.keySet()) {
                Object val = paragraph.get(key);
                if ("excerpt".equals(key)) {
                    val = this.xssAPI.filterHTML((String)val);
                }
                hit.put(key, val);
            }
            hits.put((Object)hit);
        }
        JSONObject json = new JSONObject().put("hits", (Object)hits).put("results", hits.length());
        return json;
    }

    protected String generateHtmlOutput(List<Map> paragraphs, SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        XSSAPI xssapi = (XSSAPI)request.adaptTo(XSSAPI.class);
        if (request.getParameter("itemResourceType") == null) {
            String html = "";
            for (Map paragraph : paragraphs) {
                html = html + paragraph.get("excerpt");
            }
            return xssapi.filterHTML(html);
        }
        StringResponseWrapper paragraphResponse = new StringResponseWrapper(response);
        RequestDispatcherOptions requestDispatcherOptions = new RequestDispatcherOptions(null);
        requestDispatcherOptions.setForceResourceType(request.getParameter("itemResourceType"));
        for (Map paragraph : paragraphs) {
            Resource resource;
            String path = (String)paragraph.get("path");
            if (path == null || (resource = request.getResourceResolver().getResource(path)) == null) continue;
            request.setAttribute(Resource.class.getCanonicalName(), (Object)resource);
            request.setAttribute("paragraphExcerpt", paragraph.get("excerpt"));
            RequestDispatcher dispatcher = request.getRequestDispatcher(resource.getPath(), requestDispatcherOptions);
            dispatcher.include((ServletRequest)request, (ServletResponse)paragraphResponse);
            request.removeAttribute(Resource.class.getCanonicalName());
            request.removeAttribute("paragraphExcerpt");
        }
        return xssapi.filterHTML(paragraphResponse.getString());
    }

    protected void bindXssAPI(XSSAPI xSSAPI) {
        this.xssAPI = xSSAPI;
    }

    protected void unbindXssAPI(XSSAPI xSSAPI) {
        if (this.xssAPI == xSSAPI) {
            this.xssAPI = null;
        }
    }

}