LanguageCopyCommand.java 12.4 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.commons.LanguageUtil
 *  com.day.cq.commons.jcr.JcrUtil
 *  com.day.cq.commons.servlets.HtmlStatusResponseHelper
 *  com.day.cq.i18n.I18n
 *  com.day.cq.wcm.api.PageManager
 *  com.day.cq.wcm.api.WCMException
 *  com.day.cq.wcm.api.commands.WCMCommand
 *  com.day.cq.wcm.api.commands.WCMCommandContext
 *  com.day.cq.wcm.commons.ReferenceSearch
 *  com.day.text.Text
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.nodetype.NodeType
 *  javax.servlet.http.HttpServletRequest
 *  org.apache.commons.lang.StringUtils
 *  org.apache.felix.scr.annotations.Component
 *  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.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.msm.impl.commands;

import com.day.cq.commons.LanguageUtil;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.commons.servlets.HtmlStatusResponseHelper;
import com.day.cq.i18n.I18n;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.WCMException;
import com.day.cq.wcm.api.commands.WCMCommand;
import com.day.cq.wcm.api.commands.WCMCommandContext;
import com.day.cq.wcm.commons.ReferenceSearch;
import com.day.cq.wcm.msm.impl.Utils;
import com.day.text.Text;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Service
public class LanguageCopyCommand
implements WCMCommand {
    private final Logger log = LoggerFactory.getLogger(LanguageCopyCommand.class);
    public static final String CREATE_NON_EMPTY_ANCESTORS_PARAM = "createNonEmptyAncestors";

    public String getCommandName() {
        return "copyLanguages";
    }

    public HtmlResponse performCommand(WCMCommandContext ctx, SlingHttpServletRequest request, SlingHttpServletResponse response, PageManager pageManager) {
        try {
            String rootPath = request.getParameter("path");
            if (rootPath == null || rootPath.length() == 0) {
                this.log.error("'path' param missing.");
                return HtmlStatusResponseHelper.createStatusResponse((boolean)false, (String)I18n.get((HttpServletRequest)request, (String)"Invalid request"), (String)"");
            }
            Resource res = request.getResourceResolver().getResource(rootPath);
            if (res == null) {
                this.log.error("Resource does not exist: " + rootPath);
                return HtmlStatusResponseHelper.createStatusResponse((boolean)false, (String)I18n.get((HttpServletRequest)request, (String)"Resource does not exist."), (String)rootPath);
            }
            boolean copyMissingAncestors = "true".equalsIgnoreCase(request.getParameter("createNonEmptyAncestors"));
            TreeMap<String, Info> infos = new TreeMap<String, Info>(new Comparator<String>(){

                @Override
                public int compare(String o1, String o2) {
                    return Text.compareHandles((String)o1, (String)o2);
                }
            });
            Enumeration e = request.getParameterNames();
            while (e.hasMoreElements()) {
                String dstPath;
                String srcPath;
                String name = e.nextElement().toString();
                String source = request.getParameter(name);
                int idx = name.indexOf(47);
                if (idx <= 0) continue;
                boolean deep = false;
                if (source.endsWith("+")) {
                    deep = true;
                    source = source.substring(0, source.length() - 1);
                }
                if (idx == name.length() - 1) {
                    dstPath = rootPath + "/" + name.substring(0, idx);
                    srcPath = source.equals("-") ? null : rootPath + "/" + source;
                    infos.put(dstPath, new Info(srcPath, deep));
                    continue;
                }
                dstPath = rootPath + "/" + name;
                srcPath = source.equals("-") ? null : rootPath + "/" + source + name.substring(idx);
                infos.put(dstPath, new Info(srcPath, deep));
            }
            Session session = (Session)request.getResourceResolver().adaptTo(Session.class);
            while (!infos.isEmpty()) {
                String dstPath = (String)infos.keySet().iterator().next();
                this.copyLanguage(infos, dstPath, session, pageManager, copyMissingAncestors);
            }
            return HtmlStatusResponseHelper.createStatusResponse((boolean)true, (String)I18n.get((HttpServletRequest)request, (String)"Pages Copied"), (String)rootPath);
        }
        catch (Exception e) {
            this.log.error("Error during page creation.", (Throwable)e);
            return HtmlStatusResponseHelper.createStatusResponse((boolean)false, (String)e.getMessage());
        }
    }

    private void copyLanguage(Map<String, Info> infos, String dstPath, Session session, PageManager pageManager, boolean copyMissingAncestors) throws RepositoryException, WCMException {
        Info info = infos.remove(dstPath);
        if (info.srcPath == null) {
            return;
        }
        String[] elements = Text.explode((String)dstPath, (int)47);
        Node dstParent = session.getRootNode();
        for (int i = 0; i < elements.length - 1; ++i) {
            String name = elements[i];
            if (dstParent.hasNode(name)) {
                dstParent = dstParent.getNode(name);
                continue;
            }
            if (copyMissingAncestors) {
                HashMap<String, Info> missingAncestorInfos = new HashMap<String, Info>();
                String missingDestSourcePath = this.getSourceForMissingDest(info.srcPath, i);
                if (StringUtils.isEmpty((String)missingDestSourcePath)) {
                    this.log.error("Could not identify the source path for creating a copy for missing ancestor {}!", (Object)info.srcPath);
                }
                Info missingAncestor = new Info(missingDestSourcePath, false);
                Node ancestorSource = session.getRootNode().getNode(missingDestSourcePath.substring(1));
                if (ancestorSource.hasNode("jcr:content")) {
                    this.copyLanguage(missingAncestorInfos, missingAncestor, ancestorSource, dstParent, name, pageManager);
                    dstParent = dstParent.getNode(name);
                    continue;
                }
                this.log.warn("Cannot copy missing ancestor from source path {}! The source path page does not have a {} content node! An empty page will be created!!!", new Object[]{missingDestSourcePath, "jcr:content"});
                dstParent = this.createEmptyPage(dstParent, name);
                continue;
            }
            dstParent = this.createEmptyPage(dstParent, name);
        }
        Node src = session.getRootNode().getNode(info.srcPath.substring(1));
        this.copyLanguage(infos, info, src, dstParent, Text.getName((String)dstPath), pageManager);
    }

    private Node createEmptyPage(Node parent, String childName) throws RepositoryException {
        Node emptyPageNode = parent.addNode(childName, "cq:Page");
        parent.save();
        return emptyPageNode;
    }

    private String getSourceForMissingDest(String childSourcePath, int missingDestLevel) {
        String sourcePath;
        sourcePath = "/";
        if (StringUtils.isNotEmpty((String)childSourcePath) && missingDestLevel >= 0) {
            String[] elements = Text.explode((String)childSourcePath, (int)47);
            if (missingDestLevel >= elements.length) {
                this.log.warn("Unable to determine child with level {} in path {}", (Object)missingDestLevel, (Object)childSourcePath);
                return "";
            }
            for (int i = 0; i < elements.length; ++i) {
                sourcePath = sourcePath + elements[i];
                if (missingDestLevel != i) {
                    sourcePath = sourcePath + "/";
                    continue;
                }
                break;
            }
        } else {
            this.log.warn("Unable to determine the missing ancestor source path (childSourcePath = {}, missingDestinationLevel = {})!", (Object)childSourcePath, (Object)missingDestLevel);
            return "";
        }
        return sourcePath;
    }

    private void copyLanguage(Map<String, Info> infos, Info info, Node src, Node dstParent, String name, PageManager pageManager) throws RepositoryException, WCMException {
        if (name == null) {
            name = src.getName();
        }
        Node srcContent = src.getNode("jcr:content");
        Node dst = null;
        dst = dstParent.hasNode(name) ? dstParent.getNode(name) : dstParent.addNode(name, src.getPrimaryNodeType().getName());
        this.order(src, dst);
        Node copy = JcrUtil.copy((Node)srcContent, (Node)dst, (String)null);
        try {
            Utils.detachLiveCopy(copy, true, false);
        }
        catch (WCMException e) {
            this.log.warn("Error during Live Copy cleanup: " + (Object)e);
        }
        pageManager.touch(dst, true, Calendar.getInstance(), true);
        ReferenceSearch ref = new ReferenceSearch();
        String srcLanguage = LanguageUtil.getLanguageRoot((String)src.getPath());
        String dstLanguage = LanguageUtil.getLanguageRoot((String)dstParent.getPath());
        if (srcLanguage == null || dstLanguage == null) {
            srcLanguage = src.getPath();
            dstLanguage = dst.getPath();
        }
        ref.adjustReferences(dst, srcLanguage, dstLanguage);
        dstParent.save();
        if (info == null || info.deep) {
            NodeIterator iter = src.getNodes();
            while (iter.hasNext()) {
                Node child = iter.nextNode();
                if (!child.isNodeType("cq:Page")) continue;
                this.copyLanguage(infos, child, dst, pageManager);
            }
        }
    }

    private void copyLanguage(Map<String, Info> infos, Node src, Node dstParent, PageManager pageManager) throws RepositoryException, WCMException {
        String dstPath = dstParent.getPath() + "/" + src.getName();
        Info info = infos.remove(dstPath);
        if (info != null) {
            if (info.srcPath == null) {
                return;
            }
            if (!info.srcPath.equals(src.getPath())) {
                src = src.getSession().getRootNode().getNode(info.srcPath.substring(1));
            }
        }
        this.copyLanguage(infos, info, src, dstParent, null, pageManager);
    }

    private void order(Node src, Node dest) throws RepositoryException {
        if (src != null && dest != null && src.getName().equals(dest.getName())) {
            Node n;
            NodeIterator srcSiblingsIterator = src.getParent().getNodes();
            while (srcSiblingsIterator.hasNext() && !(n = srcSiblingsIterator.nextNode()).getName().equals(src.getName())) {
            }
            Node destParent = dest.getParent();
            while (srcSiblingsIterator.hasNext()) {
                Node nextSrcSibling = srcSiblingsIterator.nextNode();
                if (!destParent.hasNode(nextSrcSibling.getName())) continue;
                destParent.orderBefore(dest.getName(), nextSrcSibling.getName());
                return;
            }
            destParent.orderBefore(dest.getName(), null);
        }
    }

    private static final class Info {
        private final String srcPath;
        private final boolean deep;

        private Info(String srcPath, boolean deep) {
            this.srcPath = srcPath;
            this.deep = deep;
        }
    }

}