CommentManagerImpl.java 8.99 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  org.apache.commons.lang.ArrayUtils
 *  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.ReferenceCardinality
 *  org.apache.felix.scr.annotations.ReferencePolicy
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.commons.osgi.PropertiesUtil
 *  org.osgi.framework.Bundle
 *  org.osgi.framework.ServiceReference
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.comments.internal;

import com.adobe.granite.comments.Comment;
import com.adobe.granite.comments.CommentCollection;
import com.adobe.granite.comments.CommentException;
import com.adobe.granite.comments.CommentManager;
import com.adobe.granite.comments.CommentingProvider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.ArrayUtils;
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.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
@Component
@Service
@Reference(name="commentingProvider", referenceInterface=CommentingProvider.class, cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE, policy=ReferencePolicy.DYNAMIC)
public class CommentManagerImpl
implements CommentManager {
    private static final Logger log = LoggerFactory.getLogger(CommentManagerImpl.class);
    private final Map<String, ProviderEntry> providerCache = new ConcurrentHashMap<String, ProviderEntry>(10);
    private final Map<String, ServiceReference> unhandledProviders = new ConcurrentHashMap<String, ServiceReference>();
    private ComponentContext context;

    @Override
    public <C extends CommentCollection> C getCollection(Resource target, Class<C> collectionType) throws CommentException {
        if (null == target) {
            throw new IllegalArgumentException("target may not be null");
        }
        if (null == collectionType) {
            throw new IllegalArgumentException("collectionType may not be null");
        }
        CommentingProvider provider = this.findProvider(collectionType);
        if (null != provider) {
            return provider.getCollection(target, collectionType);
        }
        log.warn("could not find provider for target [{}] and type [{}].", (Object)target.getPath(), collectionType);
        throw new CommentException("Could not find provider for given type [" + collectionType + "] and target [" + target.getPath() + "]");
    }

    @Override
    public <C extends CommentCollection> C getOrCreateCollection(Resource target, Class<C> collectionType) throws CommentException {
        C collection = this.getCollection(target, collectionType);
        return null != collection ? collection : this.createCollection(target, collectionType);
    }

    @Override
    public <C extends CommentCollection> C createCollection(Resource target, Class<C> collectionType) throws CommentException {
        if (null == target) {
            throw new IllegalArgumentException("target may not be null");
        }
        if (null == collectionType) {
            throw new IllegalArgumentException("collectionType may not be null");
        }
        C collection = this.getCollection(target, collectionType);
        if (null != collection) {
            log.warn("could not create collection for target [{}], collection already exists at [{}].", (Object)target.getPath(), (Object)collection.getPath());
            throw new CommentException("Collection already exists: " + collection.getPath());
        }
        CommentingProvider provider = this.findProvider(collectionType);
        if (null != provider) {
            return provider.createCollection(target, collectionType);
        }
        log.warn("could not find provider for target [{}] and type [{}].", (Object)target.getPath(), collectionType);
        throw new CommentException("Could not find provider for given type [" + collectionType + "] and target [" + target.getPath() + "]");
    }

    @Activate
    protected void activate(ComponentContext context) {
        this.context = context;
        for (ServiceReference ref : this.unhandledProviders.values()) {
            this.registerCommentingProvider(ref);
        }
        log.info("Activated Comment Adapter provider.");
    }

    @Deactivate
    protected void deactivate() {
        this.context = null;
        this.providerCache.clear();
    }

    protected void bindCommentingProvider(ServiceReference reference) {
        if (null == this.context) {
            this.unhandledProviders.put((String)reference.getProperty("service.pid"), reference);
        } else {
            this.registerCommentingProvider(reference);
        }
    }

    protected void unbindCommentingProvider(ServiceReference reference) {
        this.unregisterCommentingProvider(reference);
        this.unhandledProviders.remove(reference.getProperty("service.pid"));
    }

    protected void registerCommentingProvider(ServiceReference reference) {
        String key = (String)reference.getProperty("service.pid");
        String[] collectionTypes = PropertiesUtil.toStringArray((Object)reference.getProperty("provider.collectionTypes"));
        String[] commentTypes = PropertiesUtil.toStringArray((Object)reference.getProperty("provider.commentTypes"));
        this.providerCache.put(key, new ProviderEntry(collectionTypes, commentTypes, reference));
    }

    protected void unregisterCommentingProvider(ServiceReference reference) {
        String key = (String)reference.getProperty("service.pid");
        this.providerCache.remove(key);
        log.info("unbound commenting provider [{}]. got [{}] providers.", (Object)key, (Object)this.providerCache.size());
    }

    private CommentingProvider findProvider(Class type) {
        for (ProviderEntry providerEntry : this.providerCache.values()) {
            if ((!CommentCollection.class.isAssignableFrom(type) || !this.isSupportedType(providerEntry.getCollectionTypes(), type)) && (!Comment.class.isAssignableFrom(type) || !this.isSupportedType(providerEntry.getCommentTypes(), type))) continue;
            return providerEntry.getProvider();
        }
        return null;
    }

    private boolean isSupportedType(Class[] types, Class type) {
        for (Class clazz : types) {
            if (clazz != type && (type.isInterface() || !ArrayUtils.contains((Object[])type.getInterfaces(), (Object)clazz))) continue;
            return true;
        }
        return false;
    }

    private class ProviderEntry {
        private Class[] collectionTypes;
        private Class[] commentTypes;
        private ServiceReference providerRef;
        private CommentingProvider provider;

        private ProviderEntry(String[] collectionTypes, String[] commentTypes, ServiceReference providerRef) {
            this.providerRef = providerRef;
            this.collectionTypes = this.loadClasses(collectionTypes);
            this.commentTypes = this.loadClasses(commentTypes);
        }

        CommentingProvider getProvider() {
            Object providerService;
            if (null == this.provider && null != (providerService = CommentManagerImpl.this.context.locateService("commentingProvider", this.providerRef))) {
                this.provider = (CommentingProvider)providerService;
                log.info("bound new commenting provider [{}]. got [{}] providers.", (Object)this.provider.getClass().getName(), (Object)CommentManagerImpl.this.providerCache.size());
            }
            return this.provider;
        }

        public Class[] getCollectionTypes() {
            return this.collectionTypes;
        }

        public Class[] getCommentTypes() {
            return this.commentTypes;
        }

        private Class[] loadClasses(String[] classNames) {
            ArrayList<Class> list = new ArrayList<Class>();
            for (String className : classNames) {
                try {
                    list.add(this.providerRef.getBundle().loadClass(className));
                    continue;
                }
                catch (ClassNotFoundException e) {
                    log.error("error loading class: ", (Throwable)e);
                }
            }
            return list.toArray(new Class[list.size()]);
        }
    }

}