AliasesPreprocessor.java 8.24 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.Credentials
 *  javax.jcr.Node
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.SimpleCredentials
 *  javax.jcr.Value
 *  org.apache.sling.jcr.api.SlingRepository
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.replication.impl;

import com.day.cq.replication.AgentConfig;
import com.day.cq.replication.Preprocessor;
import com.day.cq.replication.ReplicationAction;
import com.day.cq.replication.ReplicationActionType;
import com.day.cq.replication.ReplicationException;
import com.day.cq.replication.ReplicationOptions;
import com.day.cq.replication.Replicator;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Value;
import org.apache.sling.jcr.api.SlingRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AliasesPreprocessor
implements Preprocessor {
    private static final String SLING_VANITY_PATH = "sling:vanityPath";
    private static final String SLING_ALIAS = "sling:alias";
    private final Logger log = LoggerFactory.getLogger(AliasesPreprocessor.class);
    private SlingRepository repository;
    private Replicator replicator;

    public AliasesPreprocessor(SlingRepository repository, Replicator replicator) {
        this.repository = repository;
        this.replicator = replicator;
    }

    @Override
    public void preprocess(ReplicationAction action, ReplicationOptions options) throws ReplicationException {
        if (options.isUpdateAlias()) {
            Session systemSession = null;
            Session session = null;
            try {
                String agentUserId;
                session = systemSession = this.repository.loginService("replicationService", null);
                AgentConfig config = action.getConfig();
                if (config != null && (agentUserId = config.getAgentUserId()) != null && agentUserId.length() > 0) {
                    session = this.repository.impersonateFromService("replicationService", (Credentials)new SimpleCredentials(agentUserId, new char[0]), null);
                }
                Collection<String> aliases = this.getAliasesFor(action.getPath(), session);
                options.addToAliasReplicated(action.getPath());
                for (String alias : aliases) {
                    if (options.isAliasReplicated(alias)) continue;
                    this.replicator.replicate(session, action.getType(), alias, options);
                }
            }
            catch (RepositoryException e) {
                throw new ReplicationException((Exception)e);
            }
            finally {
                if (session != null && session.isLive() && session != systemSession) {
                    session.logout();
                }
                if (systemSession != null && systemSession.isLive()) {
                    systemSession.logout();
                }
            }
        }
    }

    private Collection<String> getAliasesFor(String path, Session session) throws RepositoryException {
        Collection aliases = session.nodeExists(path) ? this.getAliasesAt(path, session) : Collections.emptySet();
        return aliases;
    }

    private Collection<String> getAliasesAt(String path, Session session) throws RepositoryException {
        HashSet<String> aliases = new HashSet<String>();
        HashMap<String, List<String>> mappings = new HashMap<String, List<String>>();
        for (int i = 1; i < path.length(); ++i) {
            if (path.charAt(i) != '/' && i + 1 != path.length()) continue;
            if (i + 1 == path.length()) {
                ++i;
            }
            String pathSoFar = path.substring(0, i);
            if (this.log.isDebugEnabled()) {
                this.log.debug("checking {}", (Object)pathSoFar);
            }
            Node candidateNode = session.getNode(pathSoFar);
            List<String> aliasNodeNames = this.getAliasNodeNames(candidateNode);
            for (String aliasNodeName : aliasNodeNames) {
                if (aliasNodeName == null) continue;
                String substitution = aliasNodeName.startsWith("/") ? aliasNodeName : candidateNode.getParent().getPath() + "/" + aliasNodeName;
                String aliasedPath = path.replace(pathSoFar, substitution);
                this.mergeExistingMappings(aliases, mappings, pathSoFar, aliasedPath);
                if (mappings.get(pathSoFar) == null) {
                    LinkedList<String> subs = new LinkedList<String>();
                    subs.add(substitution);
                    mappings.put(pathSoFar, subs);
                } else {
                    mappings.get(pathSoFar).add(substitution);
                }
                if (this.log.isDebugEnabled()) {
                    this.log.debug("added mapping {} -> {}", (Object)pathSoFar, (Object)substitution);
                }
                aliases.add(aliasedPath);
                if (!this.log.isDebugEnabled()) continue;
                this.log.debug("added alias {}", (Object)aliasedPath);
            }
        }
        return aliases;
    }

    private void mergeExistingMappings(Collection<String> aliases, Map<String, List<String>> mappings, String pathSoFar, String aliasedPath) {
        for (Map.Entry<String, List<String>> mk : mappings.entrySet()) {
            String source = mk.getKey();
            if (!pathSoFar.contains(source)) continue;
            List<String> substitutions = mk.getValue();
            for (String substitution : substitutions) {
                if (!aliasedPath.startsWith(source)) continue;
                String suffix = aliasedPath.substring(source.length());
                String newAlias = substitution + suffix;
                this.log.debug("added alias {}", (Object)newAlias);
                aliases.add(newAlias);
                this.mergeExistingMappings(aliases, mappings, pathSoFar, newAlias);
            }
        }
    }

    private List<String> getAliasNodeNames(Node candidateNode) throws RepositoryException {
        LinkedList<String> aliasNodeNames = new LinkedList<String>();
        if (candidateNode.hasProperty("sling:vanityPath")) {
            Property property = candidateNode.getProperty("sling:vanityPath");
            if (property.isMultiple()) {
                for (Value v : property.getValues()) {
                    String aliasNodeName = v.getString();
                    int selectorsAndExtensionsIndex = aliasNodeName.indexOf(46);
                    if (selectorsAndExtensionsIndex > 0) {
                        aliasNodeName = aliasNodeName.substring(0, selectorsAndExtensionsIndex);
                    }
                    aliasNodeNames.add(aliasNodeName);
                }
            } else {
                String aliasNodeName = property.getString();
                int selectorsAndExtensionsIndex = aliasNodeName.indexOf(46);
                if (selectorsAndExtensionsIndex > 0) {
                    aliasNodeName = aliasNodeName.substring(0, selectorsAndExtensionsIndex);
                }
                aliasNodeNames.add(aliasNodeName);
            }
        } else if (candidateNode.hasProperty("sling:alias")) {
            Property property = candidateNode.getProperty("sling:alias");
            if (property.isMultiple()) {
                for (Value v : property.getValues()) {
                    String aliasNodeName = v.getString();
                    int selectorsAndExtensionsIndex = aliasNodeName.indexOf(46);
                    if (selectorsAndExtensionsIndex > 0) {
                        aliasNodeName = aliasNodeName.substring(0, selectorsAndExtensionsIndex);
                    }
                    aliasNodeNames.add(aliasNodeName);
                }
            } else {
                aliasNodeNames.add(property.getString());
            }
        }
        if (candidateNode.hasNode("jcr:content")) {
            return this.getAliasNodeNames(candidateNode.getNode("jcr:content"));
        }
        return aliasNodeNames;
    }
}