All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.cq.social.scf.core.operations.AbstractOperationService Maven / Gradle / Ivy

There is a newer version: 6.5.21
Show newest version
/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2013 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.adobe.cq.social.scf.core.operations;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.request.RequestParameterMap;
import org.apache.sling.api.resource.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.cq.social.scf.InheritedOperationExtension;
import com.adobe.cq.social.scf.InheritedOperationExtensionManager;
import com.adobe.cq.social.scf.Operation;
import com.adobe.cq.social.scf.OperationException;
import com.adobe.cq.social.scf.OperationExtension;
import com.adobe.cq.social.scf.OperationService;
import com.adobe.cq.social.scf.SocialComponent;

/**
 * Abstract class that implements {@link OperationService}. This class provides the necessary functionality to
 * bind/unbind OperationExtentions and to perform before and after actions.
 * @param  the specific type of {@link OperationExtension} supported by this service.
 * @param  the specific set of operations supported by this service.
 * @param  the object representing the resource/component that the service was performed on.
 */
@SuppressWarnings("rawtypes")
public abstract class AbstractOperationService implements
    OperationService {

    protected final Map> extensionProviders = new ConcurrentHashMap>(10);
    /**
     * Logger.
     */
    private static final Logger LOG = LoggerFactory.getLogger(AbstractOperationService.class);

    @SuppressWarnings("unchecked")
    @Override
    public synchronized void addOperationExtension(final T extension) {
        for (final Object op : extension.getOperationsToHookInto()) {
            SortedSet providers;
            final U operation = (U) op;
            if (this.extensionProviders.containsKey(operation)) {
                providers = this.extensionProviders.get(operation);
            } else {
                providers = Collections.synchronizedSortedSet(new TreeSet(new Comparator() {
                    @Override
                    public int compare(final T a, final T b) {
                        return a.getOrder() - b.getOrder();
                    }
                }));
            }
            providers.add(extension);
            this.extensionProviders.put(operation, providers);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public synchronized void removeOperationExtension(final T extension) {
        for (final Object op : extension.getOperationsToHookInto()) {
            SortedSet providers;
            final U operation = (U) op;
            if (this.extensionProviders.containsKey(operation)) {
                providers = this.extensionProviders.get(operation);
                providers.remove(extension);
                this.extensionProviders.put(operation, providers);
            }
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public InheritedOperationExtensionManager getInheritedOperationExtensionManager() {
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void performBeforeActions(final U operation, final Session session, final Resource resource,
        final Map requestParameters) throws OperationException {
        if (this.extensionProviders.containsKey(operation)) {
            for (final T extension : this.extensionProviders.get(operation)) {
                extension.beforeAction(operation, session, resource, requestParameters);
            }
        }
        final InheritedOperationExtensionManager extensionManager = getInheritedOperationExtensionManager();
        if (extensionManager != null) {
            final Collection extensions =
                extensionManager.getOperationExtensions(resource);
            if (extensions != null) {
                for (final InheritedOperationExtension extension : extensions) {
                    final List hookedOperations = extension.getOperationsToHookInto();
                    for (final Operation op : hookedOperations) {
                        if (op.toString().equals(operation.toString())) {
                            extension.beforeAction(op, session, resource, requestParameters);
                        }
                    }
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void performAfterActions(final U operation, final Session session, final S component,
        final Map requestParameters) throws OperationException {

        if (this.extensionProviders.containsKey(operation)) {
            for (final T extension : this.extensionProviders.get(operation)) {
                extension.afterAction(operation, session, component, requestParameters);
            }
        }
        final InheritedOperationExtensionManager extensionManager = getInheritedOperationExtensionManager();
        if (extensionManager != null) {
            final Resource resource;
            if (component instanceof Resource) {
                resource = (Resource) component;
            } else if (component instanceof SocialComponent) {
                resource = ((SocialComponent) component).getResource();
            } else {
                resource = null;
            }
            if (resource != null) {
                final Collection extensions =
                    extensionManager.getOperationExtensions(resource);
                if (extensions != null) {
                    for (final InheritedOperationExtension extension : extensions) {
                        final List hookedOperations = extension.getOperationsToHookInto();
                        for (final Operation op : hookedOperations) {
                            if (op.toString().equals(operation.toString())) {
                                extension.afterAction(op, session, component, requestParameters);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * @param request a HTTP request that triggered the operation
     * @return a map of request parameters.
     * @throws RepositoryException if request parameters could not be converted to Value
     */
    protected Map getValueMapFromRequest(final SlingHttpServletRequest request)
        throws RepositoryException {
        final RequestParameterMap params = request.getRequestParameterMap();
        final Map map = new HashMap(params.size());
        for (final String key : params.keySet()) {
            final RequestParameter[] values = params.get(key);
            if (values.length > 0) {
                if (!key.equals("file")) {
                    final Object value =
                        (values.length == 1) ? values[0].getString() : request.getParameterValues(key);
                    map.put(key, value);
                } else {
                    final Object value = request.getRequestParameters(key);
                    map.put(key, value);
                }
            }
        }
        return map;
    }

    protected String getReferrer(final SlingHttpServletRequest request) {
        if (request != null) {
            // Use the request header value if it exists, otherwise, use the request parameter.
            String value = request.getHeader(SocialComponent.PROP_REFERER);
            if (StringUtils.isEmpty(value)) {
                value = request.getParameter(SocialComponent.PROP_REFERER);
            }
            if (StringUtils.isNotEmpty(value)) {
                try {
                    final URL url = new URL(value);
                    return url.getFile();  // only use relative path with parameters
                } catch (final MalformedURLException e) {
                    LOG.debug("Failed to get referrer property.", e);
                }
            }
        }
        return null;
    }

}