CQPagePreviewGenerator.java 12.8 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.translation.api.TranslationException
 *  com.adobe.granite.translation.api.TranslationService
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.api.PageManager
 *  com.day.cq.wcm.contentsync.PageExporter
 *  javax.jcr.Node
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.Value
 *  org.apache.commons.io.FileUtils
 *  org.apache.commons.lang3.StringUtils
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.commons.html.HtmlParser
 *  org.apache.sling.jcr.resource.JcrResourceUtil
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.wcm.translation.impl;

import com.adobe.cq.wcm.translation.impl.CQPageTranslator;
import com.adobe.cq.wcm.translation.impl.TranslationRuleConfigurationFile;
import com.adobe.cq.wcm.translation.impl.TranslationUtils;
import com.adobe.cq.wcm.translation.impl.ZipUtil;
import com.adobe.granite.translation.api.TranslationException;
import com.adobe.granite.translation.api.TranslationService;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.contentsync.PageExporter;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Set;
import java.util.UUID;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.html.HtmlParser;
import org.apache.sling.jcr.resource.JcrResourceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class CQPagePreviewGenerator
extends CQPageTranslator {
    private static final String XML_PREPROCESSOR = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>";
    private static String ATTR_NODE_PATH = "data-previewnodepath";
    private static String ATTR_PROP_NAME = "data-previewpropertyname";
    private static final Logger logger = LoggerFactory.getLogger(CQPagePreviewGenerator.class);
    private String strUniqueID;
    private String strTempFileParentPath;
    private int iCount;
    HashMap<String, ElementTextProperty> contentHashMap = null;

    public CQPagePreviewGenerator(TranslationRuleConfigurationFile ruleFile) {
        super(ruleFile, null);
    }

    public FileInputStream generatePreview(ResourceResolver resourceResolver, Page originalPage) {
        try {
            PageManager pageManager = (PageManager)resourceResolver.adaptTo(PageManager.class);
            Node parentNode = ((Node)originalPage.adaptTo(Node.class)).getParent();
            Session session = (Session)resourceResolver.adaptTo(Session.class);
            this.strTempFileParentPath = "/var/contentsync/tmp/page/" + System.currentTimeMillis();
            String strParentPath = this.strTempFileParentPath + parentNode.getPath();
            String strTempPagePath = this.strTempFileParentPath + originalPage.getPath();
            JcrResourceUtil.createPath((String)strParentPath, (String)"sling:Folder", (String)"cq:ContentSyncConfig", (Session)session, (boolean)false);
            Page tempPage = pageManager.copy(originalPage, strTempPagePath, null, true, true);
            this.init();
            Node tempPageNode = (Node)tempPage.adaptTo(Node.class);
            if (this.processTranslationNode(tempPageNode)) {
                session.save();
            }
            File tempDir = File.createTempFile("preview", "zip");
            tempDir.delete();
            tempDir.mkdir();
            String strParentFilePath = "/var/contentsync/tmp" + parentNode.getPath();
            if (!session.itemExists(strParentFilePath)) {
                JcrResourceUtil.createPath((String)strParentFilePath, (String)"sling:Folder", (String)"cq:ContentSyncConfig", (Session)session, (boolean)false);
            }
            String strZipFilePath = "/var/contentsync/tmp" + originalPage.getPath() + "_temp_" + System.currentTimeMillis() + ".zip";
            String strOutputFilePath = tempDir.getAbsolutePath() + File.separator + "preview.zip";
            PageExporter exporter = this.ruleFile.getPageExporter();
            exporter.export(tempPage, resourceResolver, strZipFilePath);
            Resource zipNode = resourceResolver.resolve(strZipFilePath);
            File fileUnzipDir = new File(tempDir.getAbsolutePath() + File.separator + "unzip");
            ZipUtil.unZipToDir(zipNode, fileUnzipDir.getAbsolutePath(), 0);
            ArrayList<File> fileList = new ArrayList<File>();
            ZipUtil.getAllFiles(fileUnzipDir, fileList, false);
            for (File file : fileList) {
                if (file.isDirectory()) continue;
                this.patchFileContent(file);
            }
            ZipUtil.zipDirectory(fileUnzipDir, strOutputFilePath);
            FileUtils.deleteDirectory((File)fileUnzipDir);
            tempPageNode.remove();
            session.save();
            return new FileInputStream(strOutputFilePath);
        }
        catch (Exception ex) {
            logger.error("Error while generating preview {}", (Throwable)ex);
            return null;
        }
    }

    @Override
    protected ArrayList<String> getTranslatablePropertyListForNode(Node node) throws RepositoryException, IOException {
        Resource resource;
        String strCurrentNodePath = node.getPath();
        if (strCurrentNodePath.indexOf(this.strTempFileParentPath) == 0 && (resource = this.resourceResolver.resolve(strCurrentNodePath = strCurrentNodePath.substring(this.strTempFileParentPath.length()))) != null) {
            node = (Node)resource.adaptTo(Node.class);
        }
        return node != null ? this.ruleFile.getTranslatablePropertyListForNode(node) : null;
    }

    @Override
    protected ArrayList<String> getLanguagePatchPropertyListForNode(Node node) throws RepositoryException, IOException {
        Resource resource;
        String strCurrentNodePath = node.getPath();
        if (strCurrentNodePath.indexOf(this.strTempFileParentPath) == 0 && (resource = this.resourceResolver.resolve(strCurrentNodePath = strCurrentNodePath.substring(this.strTempFileParentPath.length()))) != null) {
            node = (Node)resource.adaptTo(Node.class);
        }
        return node != null ? this.ruleFile.getLanguagePatchPropertyListForNode(node) : null;
    }

    private void patchFileContent(File file) {
        String strFileExtension = TranslationUtils.getFileExtension(file.getAbsolutePath(), null);
        if (!StringUtils.isEmpty((CharSequence)strFileExtension) && strFileExtension.compareToIgnoreCase(".html") == 0) {
            try {
                HtmlParser parser = this.ruleFile.getHTMLParser();
                FileInputStream stream = new FileInputStream(file);
                Document document = parser.parse(null, (InputStream)stream, "UTF-8");
                org.w3c.dom.Node rootNode = document.getFirstChild();
                this.processHTMLElement(rootNode);
                stream.close();
                String strOutput = TranslationUtils.convertDOMDocumentToString(document, false);
                if (strOutput.indexOf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>") == 0) {
                    strOutput = strOutput.substring("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>".length());
                }
                strOutput = this.patchStringContent(strOutput);
                OutputStreamWriter osw = new OutputStreamWriter((OutputStream)new FileOutputStream(file.getAbsoluteFile()), "UTF-8");
                BufferedWriter bw = new BufferedWriter(osw);
                bw.write(strOutput);
                bw.close();
            }
            catch (Exception e) {
                logger.error("Error while patching file content {}", (Throwable)e);
            }
        }
    }

    private void processHTMLElement(org.w3c.dom.Node node) {
        if (node != null) {
            String nodeText;
            ElementTextProperty textProp;
            org.w3c.dom.Node parentNode;
            if (node.getNodeType() == 3 && (textProp = this.getOriginalTextProperty(nodeText = node.getTextContent().trim())) != null && (parentNode = this.getParentTagNode(node)) != null) {
                Element element = (Element)parentNode;
                element.setAttribute(ATTR_NODE_PATH, textProp.strNodePath);
                element.setAttribute(ATTR_PROP_NAME, textProp.strPropertyName);
            }
            NodeList childNodes = node.getChildNodes();
            for (int index = 0; index < childNodes.getLength(); ++index) {
                org.w3c.dom.Node childNode = childNodes.item(index);
                this.processHTMLElement(childNode);
            }
        }
    }

    private org.w3c.dom.Node getParentTagNode(org.w3c.dom.Node node) {
        while (node != null && node.getNodeType() != 1) {
            node = node.getParentNode();
        }
        return node;
    }

    private String patchStringContent(String strOutput) {
        for (String strKey : this.contentHashMap.keySet()) {
            String strOriginalText = this.contentHashMap.get((Object)strKey).strOriginalText;
            if (strOutput.indexOf(strKey) == -1) continue;
            strOutput = strOutput.replaceAll(strKey, strOriginalText);
        }
        return strOutput;
    }

    private void init() {
        this.strUniqueID = String.format("%s_%d", UUID.randomUUID().toString(), new Date().getTime());
        this.contentHashMap = new HashMap();
        this.iCount = 0;
    }

    @Override
    protected boolean processNodeProperty(Node node, Property prop, String strPropertyName) throws TranslationException {
        boolean bSave = false;
        try {
            String strNodePath = node.getPath();
            Boolean bMultiValue = prop.isMultiple();
            if (bMultiValue.booleanValue()) {
                Value[] val_array = prop.getValues();
                if (val_array != null && val_array.length > 0) {
                    ArrayList<String> strOutputArray = new ArrayList<String>();
                    for (int index = 0; index < val_array.length; ++index) {
                        Value value = val_array[index];
                        String strTranslationText = this.getTranslatableString(value);
                        if (StringUtils.isEmpty((CharSequence)strTranslationText)) continue;
                        strOutputArray.add(this.getPatchedString(strNodePath, strPropertyName, strTranslationText));
                        bSave = true;
                    }
                    String[] newVals = TranslationUtils.getStringArray(strOutputArray);
                    prop.setValue(newVals);
                }
            } else {
                Value value = prop.getValue();
                String strTranslationText = this.getTranslatableString(value);
                if (!StringUtils.isEmpty((CharSequence)strTranslationText)) {
                    prop.setValue(this.getPatchedString(strNodePath, strPropertyName, strTranslationText));
                    bSave = true;
                }
            }
        }
        catch (Exception ex) {
            logger.error("Error while processing node propery {}", (Throwable)ex);
        }
        return bSave;
    }

    private String getTranslatableString(Value value) throws IllegalStateException, RepositoryException {
        if (value != null && value.getType() == 1) {
            return value.getString();
        }
        return null;
    }

    private String getPatchedString(String strNodePath, String strPropertyName, String strOriginalText) {
        ++this.iCount;
        String strKey = String.format("%s_%d", this.strUniqueID, this.iCount);
        if (strNodePath.indexOf(this.strTempFileParentPath) == 0) {
            strNodePath = strNodePath.substring(this.strTempFileParentPath.length());
        }
        this.contentHashMap.put(strKey, new ElementTextProperty(strNodePath, strPropertyName, strOriginalText));
        return strKey;
    }

    private ElementTextProperty getOriginalTextProperty(String strKey) {
        return this.contentHashMap.get(strKey);
    }

    class ElementTextProperty {
        public String strNodePath;
        public String strPropertyName;
        public String strOriginalText;

        public ElementTextProperty(String path, String propName, String originalText) {
            this.strNodePath = path;
            this.strPropertyName = propName;
            this.strOriginalText = originalText;
        }
    }

}