ConfigManagerImpl.java 13.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.crypto.CryptoSupport
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.Property
 *  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
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Deactivate
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.jackrabbit.util.Text
 *  org.apache.sling.jcr.api.SlingRepository
 *  org.apache.sling.jcr.resource.JcrPropertyMap
 *  org.apache.sling.settings.SlingSettingsService
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.replication.impl;

import com.adobe.granite.crypto.CryptoSupport;
import com.day.cq.replication.AgentConfig;
import com.day.cq.replication.AgentConfigGroup;
import com.day.cq.replication.ConfigManager;
import com.day.cq.replication.impl.AgentConfigGroupImpl;
import com.day.cq.replication.impl.AgentConfigImpl;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
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 org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.JcrPropertyMap;
import org.apache.sling.settings.SlingSettingsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=0, immediate=1)
@Service(value={ConfigManager.class})
public class ConfigManagerImpl
implements ConfigManager,
EventListener {
    private static final Logger log = LoggerFactory.getLogger(ConfigManagerImpl.class);
    private static final Set<String> IGNORED_PROPERTIES = new HashSet<String>();
    private static final String AGENT_CONFIG_ROOT_PATH = "/etc/replication";
    @Reference
    private SlingRepository repository = null;
    @Reference
    private SlingSettingsService settingsService = null;
    @Reference
    private CryptoSupport crypto = null;
    private Session session;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Map<String, AgentConfigImpl> configurations = new TreeMap<String, AgentConfigImpl>();
    private final Map<String, AgentConfigGroupImpl> configGroups = new TreeMap<String, AgentConfigGroupImpl>();
    private final List<ConfigManager.ConfigEventListener> listeners = new LinkedList<ConfigManager.ConfigEventListener>();

    @Activate
    protected void activate() {
        this.lock.writeLock().lock();
        try {
            this.session = this.repository.loginService("replicationService", null);
            if (this.session.nodeExists("/etc/replication")) {
                this.scan(this.session.getNode("/etc/replication"));
            } else {
                log.info("Unable to read any configured agents. {} does not exist.", (Object)"/etc/replication");
            }
            this.session.getWorkspace().getObservationManager().addEventListener((EventListener)this, 31, "/etc/replication", true, null, null, true);
            log.info("ConfigManager service activated");
        }
        catch (RepositoryException e) {
            throw new IllegalStateException("Error while initializing config manager", (Throwable)e);
        }
        finally {
            this.lock.writeLock().unlock();
        }
    }

    private void scan(Node node) throws RepositoryException {
        NodeIterator iter = node.getNodes();
        while (iter.hasNext()) {
            Node n = iter.nextNode();
            if ("jcr:content".equals(n.getName())) continue;
            this.update(n);
            this.scan(n);
        }
    }

    @Deactivate
    protected void deactivate() {
        block5 : {
            this.lock.writeLock().lock();
            this.listeners.clear();
            this.configGroups.clear();
            this.configurations.clear();
            try {
                if (this.session == null) break block5;
                try {
                    this.session.getWorkspace().getObservationManager().removeEventListener((EventListener)this);
                }
                catch (RepositoryException var1_1) {
                    // empty catch block
                }
                this.session.logout();
                this.session = null;
            }
            finally {
                this.lock.writeLock().unlock();
            }
        }
    }

    private void notifyListeners(final String path, final ConfigManager.ConfigEvent.Type type) {
        ConfigManager.ConfigEvent evt = new ConfigManager.ConfigEvent(){

            @Override
            public ConfigManager.ConfigEvent.Type getType() {
                return type;
            }

            @Override
            public String getId() {
                return path;
            }
        };
        for (ConfigManager.ConfigEventListener listener : this.listeners) {
            listener.onConfigEvent(evt);
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public void onEvent(EventIterator events) {
        HashSet<String> paths = new HashSet<String>();
        while (events.hasNext()) {
            Event evt = events.nextEvent();
            try {
                int idx;
                String path = evt.getPath();
                if (evt.getType() != 1 && evt.getType() != 2) {
                    String name = Text.getName((String)path);
                    if (IGNORED_PROPERTIES.contains(name)) continue;
                    path = Text.getRelativeParent((String)path, (int)1);
                }
                if ((idx = path.indexOf("/jcr:content")) > 0) {
                    paths.add(path.substring(0, idx));
                    continue;
                }
                paths.add(path);
            }
            catch (RepositoryException e) {
                log.warn("Error while reading observation information: " + (Object)e);
            }
        }
        try {
            this.lock.writeLock().lock();
            for (String path : paths) {
                this.session.refresh(false);
                if (this.session.nodeExists(path)) {
                    Node node = this.session.getNode(path);
                    this.update(node);
                    continue;
                }
                this.configGroups.remove(path);
                AgentConfigImpl cfg = this.configurations.remove(path);
                if (cfg == null) continue;
                cfg.getConfigGroup().getConfigurations().remove(cfg.getId());
                this.notifyListeners(cfg.getId(), ConfigManager.ConfigEvent.Type.REMOVED);
            }
        }
        catch (RepositoryException e) {
            log.error("error while updating agents.", (Throwable)e);
        }
        finally {
            this.lock.writeLock().unlock();
        }
    }

    private AgentConfig loadConfig(Node node) throws RepositoryException {
        if (node.hasNode("jcr:content")) {
            String path = node.getPath();
            AgentConfigImpl cfg = this.configurations.remove(path);
            if (cfg != null) {
                cfg.getConfigGroup().getConfigurations().remove(path);
            }
            AgentConfigGroupImpl group = null;
            Node parent = node.getParent();
            while (group == null && parent.getDepth() > 0 && !parent.getPath().equals("/etc/replication")) {
                group = this.configGroups.get(parent.getPath());
                if (group == null && (group = AgentConfigGroupImpl.create(parent, this.settingsService)) != null) {
                    this.configGroups.put(parent.getPath(), group);
                }
                parent = parent.getParent();
            }
            if (group == null) {
                log.info("Possible agent configured outside of any config group: {}", (Object)path);
                return null;
            }
            Node content = node.getNode("jcr:content");
            this.makeConfigCompatible(content);
            JcrPropertyMap props = new JcrPropertyMap(content);
            HashMap<String, Object> properties = new HashMap<String, Object>((Map<String, Object>)props);
            cfg = new AgentConfigImpl(node.getPath(), properties, content.getPath(), group, this.crypto);
            group.getConfigurations().put(cfg.getId(), cfg);
            this.configurations.put(cfg.getId(), cfg);
            log.info("Configuration for agent at {} is {}active.", (Object)path, (Object)(group.isActive() ? "" : "not "));
            return cfg;
        }
        return null;
    }

    private void makeConfigCompatible(Node content) throws RepositoryException {
        if (content.hasProperty("protocolHTTPSRelaxed")) {
            Property isRelaxedSslProp = content.getProperty("protocolHTTPSRelaxed");
            if (isRelaxedSslProp.getBoolean() && !content.hasProperty("ssl")) {
                content.setProperty("ssl", "relaxed");
            }
            isRelaxedSslProp.remove();
            content.getSession().save();
        }
    }

    @Override
    public Map<String, AgentConfig> getConfigurations() {
        try {
            this.lock.readLock().lock();
            LinkedHashMap<String, AgentConfig> linkedHashMap = new LinkedHashMap<String, AgentConfig>(this.configurations);
            return linkedHashMap;
        }
        finally {
            this.lock.readLock().unlock();
        }
    }

    @Override
    public Map<String, AgentConfigGroup> getConfigGroups() {
        try {
            this.lock.readLock().lock();
            LinkedHashMap<String, AgentConfigGroup> linkedHashMap = new LinkedHashMap<String, AgentConfigGroup>(this.configGroups);
            return linkedHashMap;
        }
        finally {
            this.lock.readLock().unlock();
        }
    }

    @Override
    public void registerListener(ConfigManager.ConfigEventListener listener) {
        this.listeners.add(listener);
    }

    @Override
    public void unregisterListener(ConfigManager.ConfigEventListener listener) {
        this.listeners.remove(listener);
    }

    private void update(Node node) throws RepositoryException {
        String path = node.getPath();
        if (AgentConfigGroupImpl.getRunModes(node) != null) {
            AgentConfigGroupImpl grp = this.configGroups.get(path);
            if (grp == null) {
                grp = AgentConfigGroupImpl.create(node, this.settingsService);
                this.configGroups.put(path, grp);
            } else {
                grp.update(node);
            }
        } else {
            boolean isUpdate = this.configurations.containsKey(path);
            AgentConfig config = this.loadConfig(node);
            if (config == null) {
                this.notifyListeners(path, ConfigManager.ConfigEvent.Type.REMOVED);
            } else if (isUpdate) {
                this.notifyListeners(path, ConfigManager.ConfigEvent.Type.UPDATED);
            } else {
                this.notifyListeners(path, ConfigManager.ConfigEvent.Type.ADDED);
            }
        }
    }

    static {
        IGNORED_PROPERTIES.add("cq:name");
        IGNORED_PROPERTIES.add("cq:siblingOrder");
        IGNORED_PROPERTIES.add("cq:parentPath");
        IGNORED_PROPERTIES.add("cq:childrenOrder");
        IGNORED_PROPERTIES.add("jcr:baseVersion");
        IGNORED_PROPERTIES.add("jcr:isCheckedOut");
        IGNORED_PROPERTIES.add("jcr:predecessors");
    }

    protected void bindRepository(SlingRepository slingRepository) {
        this.repository = slingRepository;
    }

    protected void unbindRepository(SlingRepository slingRepository) {
        if (this.repository == slingRepository) {
            this.repository = null;
        }
    }

    protected void bindSettingsService(SlingSettingsService slingSettingsService) {
        this.settingsService = slingSettingsService;
    }

    protected void unbindSettingsService(SlingSettingsService slingSettingsService) {
        if (this.settingsService == slingSettingsService) {
            this.settingsService = null;
        }
    }

    protected void bindCrypto(CryptoSupport cryptoSupport) {
        this.crypto = cryptoSupport;
    }

    protected void unbindCrypto(CryptoSupport cryptoSupport) {
        if (this.crypto == cryptoSupport) {
            this.crypto = null;
        }
    }

}