ComponentExtractorServlet.java 14.4 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.Binary
 *  javax.jcr.Node
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.ValueFactory
 *  javax.servlet.Servlet
 *  javax.servlet.ServletException
 *  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.ReferencePolicy
 *  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.scripting.SlingBindings
 *  org.apache.sling.api.scripting.SlingScript
 *  org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper
 *  org.apache.sling.commons.html.HtmlParser
 *  org.apache.sling.scripting.core.ScriptHelper
 *  org.osgi.framework.BundleContext
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.siteimporter.internal.servlet;

import com.day.cq.wcm.siteimporter.ProgressTracker;
import com.day.cq.wcm.siteimporter.internal.servlet.SiteImporterServletBase;
import com.day.cq.wcm.siteimporter.internal.util.Utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFactory;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferencePolicy;
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.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScript;
import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
import org.apache.sling.commons.html.HtmlParser;
import org.apache.sling.scripting.core.ScriptHelper;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

@Component(metatype=0, label="Component Extractor", description="Extracts components from a page")
@Service(value={Servlet.class})
@Properties(value={@org.apache.felix.scr.annotations.Property(name="sling.servlet.paths", propertyPrivate=1, value={"/libs/wcm/bin/siteimporter/extract"}), @org.apache.felix.scr.annotations.Property(name="sling.servlet.methods", propertyPrivate=1, value={"POST"}), @org.apache.felix.scr.annotations.Property(name="service.description", value={"Component Extractor Servlet"})})
public class ComponentExtractorServlet
extends SiteImporterServletBase {
    private static final long serialVersionUID = 9112167990766136591L;
    private static final Logger log = LoggerFactory.getLogger(ComponentExtractorServlet.class);
    protected static final String COMPONENT_TPL = "wcm/siteimporter/resources/component.esp";
    @Reference(policy=ReferencePolicy.STATIC)
    private HtmlParser parser;
    private BundleContext bundleCtx;

    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");
        ResourceResolver resolver = request.getResourceResolver();
        String status = request.getParameter(":status");
        boolean isBrowser = status != null && status.equals("browser");
        String path = request.getParameter("path");
        String label = request.getParameter("label");
        String res = request.getParameter("resource");
        String id = request.getParameter("insertID");
        boolean overwrite = "true".equals(request.getParameter("overwrite"));
        if (!(path == null || label == null || label.equals("") || res == null || res.equals("") || id == null || id.equals(""))) {
            Node node;
            String charset = null;
            Resource resource = resolver.getResource(res);
            if (resource != null && (node = (Node)resource.adaptTo(Node.class)) != null) {
                try {
                    Node parent = node.getParent();
                    if (parent.hasProperty("cqProjectCharset")) {
                        charset = parent.getProperty("cqProjectCharset").getString();
                    }
                }
                catch (RepositoryException e) {
                    log.error("Could not read charset", (Throwable)e);
                }
            }
            ProgressTracker out = this.getOutput();
            String html = Utils.readFileNode(res, resolver, out);
            if ((html = this.extractComponentHtml(id, html, charset, out)) != null) {
                Resource parent = resolver.getResource(path);
                if (parent != null) {
                    try {
                        this.createComponent(parent, label, html, charset, request, response, isBrowser, overwrite);
                    }
                    catch (Exception e) {
                        log.error("Could not create component", (Throwable)e);
                        this.sendResponse(500, "Could not create component", response, isBrowser);
                    }
                } else {
                    this.sendResponse(500, "Parent path could not be found", response, isBrowser);
                }
            } else {
                this.sendResponse(500, "Couldn't extract component HTML", response, isBrowser);
            }
        } else {
            this.sendResponse(400, "Invalid parameters", response, isBrowser);
        }
    }

    protected void activate(ComponentContext context) throws RepositoryException {
        this.bundleCtx = context.getBundleContext();
    }

    private String extractComponentHtml(String id, String html, String charset, ProgressTracker out) {
        Document doc = Utils.parse(html, charset, this.parser, out);
        XPath xpath = XPathFactory.newInstance().newXPath();
        Element el = null;
        try {
            el = (Element)xpath.evaluate("//*[@componentinsertid='" + id + "']", doc, XPathConstants.NODE);
        }
        catch (XPathExpressionException e) {
            out.error("Couldn't get element: " + e.getMessage(), e);
            return null;
        }
        if (el != null) {
            Utils.removeInsertIds(el);
            DOMSource source = new DOMSource(el);
            ByteArrayOutputStream transContent = new ByteArrayOutputStream();
            try {
                TransformerFactory tf = TransformerFactory.newInstance();
                Transformer xformer = tf.newTransformer();
                if (charset != null) {
                    xformer.setOutputProperty("encoding", charset);
                }
                xformer.setOutputProperty("omit-xml-declaration", "yes");
                xformer.transform(source, new StreamResult(transContent));
            }
            catch (Exception e) {
                out.error("Couldn't parse original HTML: " + e.getMessage(), e);
                return null;
            }
            if (charset != null) {
                try {
                    return new String(transContent.toByteArray(), charset);
                }
                catch (UnsupportedEncodingException e) {
                    return new String(transContent.toByteArray());
                }
            }
            return new String(transContent.toByteArray());
        }
        return null;
    }

    private void createComponent(Resource parent, String label, String compHtml, String charset, SlingHttpServletRequest request, SlingHttpServletResponse response, boolean isBrowser, boolean overwrite) throws Exception {
        Node node = (Node)parent.adaptTo(Node.class);
        if (node != null) {
            String supertype;
            String path;
            String allowedParents;
            String description;
            String group;
            if (node.hasNode(label) && overwrite) {
                node.getNode(label).remove();
                node.getSession().save();
            }
            Node comp = node.addNode(label, "cq:Component");
            String title = request.getParameter("title");
            if (title != null && !title.equals("")) {
                comp.setProperty("jcr:title", title);
            }
            if ((description = request.getParameter("description")) != null && !description.equals("")) {
                comp.setProperty("jcr:description", description);
            }
            if ((group = request.getParameter("group")) != null && !group.equals("")) {
                comp.setProperty("componentGroup", group);
            }
            if ((supertype = request.getParameter("supertype")) != null && !supertype.equals("")) {
                comp.setProperty("sling:resourceSuperType", supertype);
            }
            if ((allowedParents = request.getParameter("allowedParents")) != null && !allowedParents.equals("")) {
                comp.setProperty("allowedParents", allowedParents);
            }
            ResourceResolver resolver = parent.getResourceResolver();
            Resource compTpl = null;
            String[] arr$ = resolver.getSearchPath();
            int len$ = arr$.length;
            for (int i$ = 0; i$ < len$ && (compTpl = resolver.getResource((path = arr$[i$]) + "/" + "wcm/siteimporter/resources/component.esp")) == null; ++i$) {
            }
            if (compTpl != null) {
                SlingScript script = (SlingScript)compTpl.adaptTo(SlingScript.class);
                if (script != null) {
                    ResponseWrapper respWrap = new ResponseWrapper(response, charset);
                    ScriptHelper helper = new ScriptHelper(this.bundleCtx, script, request, (SlingHttpServletResponse)respWrap);
                    SlingBindings props = new SlingBindings();
                    props.put((Object)"scriptHelper", (Object)helper);
                    props.put((Object)"title", (Object)title);
                    props.put((Object)"description", (Object)description);
                    props.put((Object)"html", (Object)compHtml);
                    props.setRequest(request);
                    props.setResponse((SlingHttpServletResponse)respWrap);
                    script.eval(props);
                    Node jspFile = comp.addNode(label + ".jsp", "nt:file");
                    Node jspContent = jspFile.addNode("jcr:content", "nt:resource");
                    ValueFactory vf = jspContent.getSession().getValueFactory();
                    jspContent.setProperty("jcr:data", vf.createBinary(respWrap.getStream()));
                    jspContent.setProperty("jcr:mimeType", "text/plain");
                    jspContent.setProperty("jcr:lastModified", (Calendar)new GregorianCalendar());
                } else {
                    this.sendResponse(500, "Component template is not a valid script", response, isBrowser);
                }
            } else {
                this.sendResponse(500, "Component template could not be found", response, isBrowser);
            }
            Node dialog = comp.addNode("dialog", "cq:Dialog");
            dialog.setProperty("title", title);
            dialog.setProperty("xtype", "panel");
            Node items = dialog.addNode("items", "cq:WidgetCollection");
            Node textField = items.addNode("text", "cq:Widget");
            textField.setProperty("xtype", "richtext");
            textField.setProperty("name", "./text");
            textField.setProperty("hideLabel", true);
            Node isRich = items.addNode("isRichTextFlag", "cq:Widget");
            isRich.setProperty("xtype", "hidden");
            isRich.setProperty("name", "./textIsRich");
            isRich.setProperty("ignoreData", true);
            isRich.setProperty("value", true);
            node.getSession().save();
            this.sendResponse(200, "Component successfully created", response, isBrowser);
        } else {
            this.sendResponse(500, "Parent path could not be found in repository", response, isBrowser);
        }
    }

    protected void bindParser(HtmlParser htmlParser) {
        this.parser = htmlParser;
    }

    protected void unbindParser(HtmlParser htmlParser) {
        if (this.parser == htmlParser) {
            this.parser = null;
        }
    }

    class ResponseWrapper
    extends SlingHttpServletResponseWrapper {
        private CharArrayWriter output;
        private String charset;

        public ResponseWrapper(SlingHttpServletResponse response, String charset) {
            super(response);
            this.output = new CharArrayWriter();
            this.charset = charset;
        }

        public InputStream getStream() {
            byte[] buf;
            if (this.charset != null) {
                try {
                    buf = this.output.toString().getBytes(this.charset);
                }
                catch (UnsupportedEncodingException e) {
                    buf = this.output.toString().getBytes();
                }
            } else {
                buf = this.output.toString().getBytes();
            }
            return new ByteArrayInputStream(buf);
        }

        public PrintWriter getWriter() {
            return new PrintWriter(this.output);
        }

        public String toString() {
            return this.output.toString();
        }
    }

}