LiveCopyIndexImpl.java 12.5 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.wcm.api.WCMException
 *  javax.jcr.Node
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.Workspace
 *  javax.jcr.observation.Event
 *  javax.jcr.observation.EventIterator
 *  javax.jcr.observation.EventListener
 *  javax.jcr.observation.ObservationManager
 *  javax.jcr.query.QueryManager
 *  org.apache.commons.lang.StringUtils
 *  org.apache.jackrabbit.api.observation.JackrabbitEventFilter
 *  org.apache.jackrabbit.api.observation.JackrabbitObservationManager
 *  org.apache.jackrabbit.util.Text
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.msm.impl;

import com.day.cq.wcm.api.WCMException;
import com.day.cq.wcm.msm.impl.LiveCopyManagerImpl;
import com.day.cq.wcm.msm.impl.SourceTargetFilter;
import com.day.cq.wcm.msm.impl.SourceTargetMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Workspace;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
import javax.jcr.observation.ObservationManager;
import javax.jcr.query.QueryManager;
import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.api.observation.JackrabbitEventFilter;
import org.apache.jackrabbit.api.observation.JackrabbitObservationManager;
import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LiveCopyIndexImpl {
    private static final Logger log = LoggerFactory.getLogger(LiveCopyIndexImpl.class);
    private final Session session;
    private final String rootPath;
    private final String[] excludedPaths;
    private final SourceTargetMap index;
    private boolean indexedFully = false;
    private EventListener nodeListener;
    private EventListener propertyListener;
    private boolean stopped;

    /* varargs */ LiveCopyIndexImpl(Session session, String rootPath, String ... excludedPaths) throws RepositoryException {
        Workspace wsp = session.getWorkspace();
        ObservationManager om = wsp.getObservationManager();
        QueryManager qm = wsp.getQueryManager();
        if (qm == null) {
            throw new IllegalArgumentException("Need QueryManager for Workspace");
        }
        if (om == null) {
            throw new IllegalArgumentException("Need ObservationManager");
        }
        this.session = session;
        this.rootPath = rootPath;
        this.index = new SourceTargetMap();
        this.excludedPaths = excludedPaths;
    }

    synchronized SourceTargetFilter get(String targetPath) throws RepositoryException, WCMException {
        return this.update(targetPath);
    }

    synchronized SourceTargetFilter update(String path) throws WCMException, RepositoryException {
        if (this.index.filterAt(path)) {
            this.index.remove(path);
        }
        return this.read(path);
    }

    private SourceTargetFilter read(String targetPath) throws RepositoryException, WCMException {
        SourceTargetFilter sourceTargetFilter = null;
        this.session.refresh(false);
        if (this.session.nodeExists(targetPath)) {
            Node contentNode;
            Node lcNode = this.session.getNode(targetPath);
            if (lcNode.isNodeType("nt:hierarchyNode") && lcNode.hasNode("jcr:content")) {
                contentNode = lcNode.getNode("jcr:content");
            } else if (!lcNode.isNodeType("nt:hierarchyNode")) {
                contentNode = lcNode;
            } else {
                return null;
            }
            if (LiveCopyManagerImpl.hasLiveCopy(contentNode)) {
                Node configNode = contentNode.getNode("cq:LiveSyncConfig");
                sourceTargetFilter = SourceTargetFilter.read(configNode);
                this.index.addSourTargetFilter(sourceTargetFilter);
            }
        }
        return sourceTargetFilter;
    }

    synchronized Set<String> getTargetLiveCopies(String sourcePath) throws RepositoryException, WCMException {
        log.debug("Get target LiveCopies for {}", (Object)sourcePath);
        this.buildIndex();
        return this.index.getTargets(sourcePath);
    }

    synchronized SourceTargetFilter getClosestLiveCopy(String path) throws RepositoryException, WCMException {
        if (this.indexedFully) {
            return this.index.getContainingFilter(Text.getRelativeParent((String)path, (int)1));
        }
        String check = path;
        while (!(check = Text.getRelativeParent((String)check, (int)1)).equals("/")) {
            SourceTargetFilter parent = this.get(check);
            if (parent == null) continue;
            if (parent.contains(path)) {
                log.debug("Found a LiveCopy for {} at {}", (Object)path, (Object)check);
                return parent;
            }
            log.debug("Found a shallow LiveCopy for {} at {}: not contained in a LiveCopy", (Object)path, (Object)check);
            return null;
        }
        return null;
    }

    synchronized List<String> getTargetBranch(String targetPath) throws WCMException, RepositoryException {
        this.buildIndex();
        return this.index.getTargetBranch(targetPath);
    }

    void setDirty() {
        this.indexedFully = false;
    }

    void startListening() throws RepositoryException {
        this.nodeListener = new EventListener(){

            /*
             * WARNING - Removed try catching itself - possible behaviour change.
             */
            public void onEvent(EventIterator events) {
                HashSet<String> processed = new HashSet<String>();
                String path = "";
                block10 : do {
                    try {
                        Event event;
                        boolean isConfig;
                        do {
                            if (!events.hasNext()) break block10;
                            event = events.nextEvent();
                            path = event.getPath();
                            isConfig = false;
                            if (!path.endsWith("cq:LiveSyncConfig")) continue;
                            isConfig = true;
                            if (!StringUtils.isEmpty((String)(path = Text.getRelativeParent((String)path, (int)2)))) continue;
                            path = "/";
                        } while (processed.contains(path));
                        LiveCopyIndexImpl liveCopyIndexImpl = LiveCopyIndexImpl.this;
                        synchronized (liveCopyIndexImpl) {
                            processed.add(path);
                            switch (event.getType()) {
                                case 32: {
                                    if (LiveCopyIndexImpl.this.index.descendantHasFilter(path)) {
                                        LiveCopyIndexImpl.this.flushAll();
                                        return;
                                    }
                                    processed.remove(path);
                                    break;
                                }
                                case 2: {
                                    if (!LiveCopyIndexImpl.this.index.descendantHasFilter(path)) break;
                                    LiveCopyIndexImpl.this.updatePath(path);
                                    break;
                                }
                                case 1: {
                                    if (!LiveCopyIndexImpl.this.indexedFully) break;
                                    if (!isConfig) {
                                        String contentPath = event.getPath() + "/" + "jcr:content";
                                        boolean bl = isConfig = LiveCopyIndexImpl.this.session.nodeExists(contentPath) && LiveCopyManagerImpl.hasLiveCopy(LiveCopyIndexImpl.this.session.getNode(contentPath));
                                    }
                                    if (!isConfig) break;
                                    LiveCopyIndexImpl.this.get(path);
                                }
                            }
                            continue;
                        }
                    }
                    catch (Exception e) {
                        if (LiveCopyIndexImpl.this.stopped) {
                            log.debug("Failed to process Event at {}: {}: Event dispatched while unregistered", (Object)path, (Object)e);
                            break;
                        }
                        LiveCopyIndexImpl.this.flushAll();
                        log.error("Failed to process Event at {}: {}: clear Index", (Object)path, (Object)e);
                        break;
                    }
                } while (true);
            }
        };
        this.propertyListener = new EventListener(){

            /*
             * WARNING - Removed try catching itself - possible behaviour change.
             */
            public void onEvent(EventIterator events) {
                HashSet<String> processed = new HashSet<String>();
                String path = "";
                try {
                    while (events.hasNext()) {
                        Event event = events.nextEvent();
                        path = Text.getRelativeParent((String)event.getPath(), (int)3);
                        if (StringUtils.isEmpty((String)path) || processed.contains(path)) continue;
                        LiveCopyIndexImpl liveCopyIndexImpl = LiveCopyIndexImpl.this;
                        synchronized (liveCopyIndexImpl) {
                            LiveCopyIndexImpl.this.update(path);
                        }
                        processed.add(path);
                    }
                }
                catch (Exception e) {
                    if (LiveCopyIndexImpl.this.stopped) {
                        log.debug("Failed to process Event at {}: {}: Event dispatched while unregistered", (Object)path, (Object)e);
                    }
                    LiveCopyIndexImpl.this.flushAll();
                    log.error("Failed to process Event at {}: {}: clear Index", (Object)path, (Object)e);
                }
            }
        };
        JackrabbitObservationManager om = (JackrabbitObservationManager)this.session.getWorkspace().getObservationManager();
        JackrabbitEventFilter nodeListenerFilter = new JackrabbitEventFilter().setAbsPath(this.rootPath).setEventTypes(35).setIsDeep(true).setNoLocal(true);
        if (this.excludedPaths != null && this.excludedPaths.length > 0) {
            nodeListenerFilter.setExcludedPaths(this.excludedPaths);
        }
        om.addEventListener(this.nodeListener, nodeListenerFilter);
        JackrabbitEventFilter propertyListenerFilter = new JackrabbitEventFilter().setAbsPath(this.rootPath).setEventTypes(28).setIsDeep(true).setNodeTypes(new String[]{"cq:LiveSyncConfig"}).setNoLocal(false);
        if (this.excludedPaths != null && this.excludedPaths.length > 0) {
            propertyListenerFilter.setExcludedPaths(this.excludedPaths);
        }
        om.addEventListener(this.propertyListener, propertyListenerFilter);
    }

    void endListening() throws RepositoryException {
        ObservationManager om;
        this.stopped = true;
        if (this.session.isLive() && (om = this.session.getWorkspace().getObservationManager()) != null) {
            if (this.nodeListener != null) {
                om.removeEventListener(this.nodeListener);
            }
            if (this.propertyListener != null) {
                om.removeEventListener(this.propertyListener);
            }
        }
    }

    private synchronized void flushAll() {
        this.setDirty();
        this.index.clear();
    }

    private synchronized void buildIndex() throws RepositoryException, WCMException {
        if (!this.indexedFully) {
            this.session.refresh(false);
            for (SourceTargetFilter f : SourceTargetFilter.getAll(this.rootPath, this.session, new HashSet<SourceTargetFilter>())) {
                this.index.addSourTargetFilter(f);
            }
            this.indexedFully = true;
        }
    }

    private void updatePath(String path) throws RepositoryException, WCMException {
        for (String des : this.index.getTargetBranch(path)) {
            this.update(des);
        }
    }

    void events(EventIterator events, int type) {
        switch (type) {
            case 1: 
            case 2: 
            case 32: {
                this.nodeListener.onEvent(events);
                break;
            }
            default: {
                this.propertyListener.onEvent(events);
            }
        }
    }

}