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

com.adobe.cq.social.scf.core.operations.AbstractSocialOperation 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.lang.reflect.AnnotatedElement;
import java.net.MalformedURLException;
import java.net.URL;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.api.wrappers.SlingRequestPaths;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.servlets.post.JSONResponse;
import org.apache.sling.servlets.post.PostOperation;
import org.apache.sling.servlets.post.PostResponse;
import org.apache.sling.servlets.post.SlingPostConstants;
import org.apache.sling.servlets.post.SlingPostProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.cq.social.commons.annotation.Endpoint;
import com.adobe.cq.social.commons.annotation.Parameters;
import com.adobe.cq.social.scf.JsonException;
import com.adobe.cq.social.scf.OperationException;
import com.adobe.cq.social.scf.SocialComponent;
import com.adobe.cq.social.scf.SocialOperationInfo;
import com.adobe.cq.social.scf.SocialOperationResult;
import com.adobe.cq.social.ugcbase.core.SocialResourceUtils;

/**
 * Abstract class that implements PostOperation and provides utility methods to send correct HTTP responses. This
 * class can be extended to implement PostOperations for components.
 */
@Component(metatype = false, componentAbstract = true)
public abstract class AbstractSocialOperation implements PostOperation, SocialOperationInfo {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractSocialOperation.class);

    @Override
    public final void run(final SlingHttpServletRequest request, final PostResponse response,
        final SlingPostProcessor[] processors) {
        try {
            Resource resource = request.getResource();
            if (ResourceUtil.isNonExistingResource(resource)) {
                final RequestPathInfo pathInfo = request.getRequestPathInfo();
                String newPath = StringUtils.removeEnd(resource.getPath(), "." + pathInfo.getExtension());
                newPath = StringUtils.removeEnd(newPath, pathInfo.getSelectorString());
                final String[] selectors = pathInfo.getSelectors();
                for (int i = 0; i < selectors.length; i++) {
                    if (!StringUtils.equals(selectors[i], "social")) {
                        newPath += "." + selectors[i];
                    }
                }
                newPath = StringUtils.removeEnd(newPath, ".");
                resource = request.getResourceResolver().resolve(newPath);
            }
            final SocialOperationResult result;
            if (StringUtils.equals(request.getResource().getPath(), resource.getPath())) {
                result = this.performOperation(request);

            } else {
                result = this.performOperation(new NonExistingResourceWrappingRequest(request, resource));
            }
            this.sendResponse(result, request, response);
        } catch (final OperationException e) {
            this.sendResponse(e, request, response);
        } catch (final Throwable t) {
            LOG.error("Error performing operation: ", t);
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                this.sendResponse(new OperationException(t, 500), request, response);
            }
        }

    }

    /**
     * Default implementation of {@link SocialOperationInfo} interface. {@inheritDoc}
     */
    @Override
    public final Endpoint getEndpoint() {
        Endpoint endpoint = null;
        final Class klass = this.getClass();
        if (klass.isAnnotationPresent(Endpoint.class)) {
            final AnnotatedElement element = klass;
            endpoint = element.getAnnotation(Endpoint.class);
        }
        return endpoint;
    }

    /**
     * Default implementation of {@link SocialOperationInfo} interface. {@inheritDoc}
     */
    @Override
    public final Parameters getRequestParameters() {
        Parameters parameters = null;
        final Class klass = this.getClass();
        if (klass.isAnnotationPresent(Parameters.class)) {
            final AnnotatedElement element = klass;
            parameters = element.getAnnotation(Parameters.class);
        }
        return parameters;
    }

    /**
     * @param e an exception thrown by the operation that defines the HTTP response status and message.
     * @param request the request that triggered the operation
     * @param response the HTTP response for the request.
     */
    protected void sendResponse(final OperationException e, final SlingHttpServletRequest request,
        final PostResponse response) {
        if (e.getErrorCode() > 499) {
            LOG.error("Error performing operation", e);
        } else {
            LOG.info("Operation exception encountered", e);
        }
        response.setError(e);
        response.setPath(request.getResource().getPath());
        response.setCreateRequest(false);
        // checkstyle ignore:line
        response.setStatus(e.getErrorCode(), e.getMessage());

    }

    /**
     * @param result the result returned after performing the operation.
     * @param request the request that triggered the operation
     * @param response the HTTP response for the request.
     */
    protected void sendResponse(final SocialOperationResult result, final SlingHttpServletRequest request,
        final PostResponse response) {
        response.setStatus(result.getHttpStatusCode(), result.getHttpStatusMessage());
        response.setLocation(this.externalizePath(request, result.getPath()));
        response.setPath(request.getResource().getPath());
        if (response instanceof JSONResponse && result.getResource() != null) {
            try {
                ((JSONResponse) response).setProperty("response",
                    new JSONObject(result.getResource().toJSONString(false)));
            } catch (final JsonException e) {
                LOG.error("Error trying to write JSON response for " + result.getResource().getId(), e);
                // checkstyle ignore:line
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
            } catch (final JSONException e) {
                LOG.error("Error trying to write JSON response for " + result.getResource().getId(), e);
                // checkstyle ignore:line
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
            }

        }
    }

    /**
     * @param request the request that triggered the operation.
     * @param path path to resource that was touched by the operation.
     * @return the externalized URL to the resource.
     */
    protected final String externalizePath(final SlingHttpServletRequest request, final String path) {
        final StringBuffer ret = new StringBuffer();
        ret.append(SlingRequestPaths.getContextPath(request));
        if (!SocialResourceUtils.isCloudUGC(path)) {
            ret.append(request.getResourceResolver().map(path));
        } else {
            ret.append(path);
        }

        // append optional extension
        final String ext = request.getParameter(SlingPostConstants.RP_DISPLAY_EXTENSION);
        if (ext != null && ext.length() > 0) {
            if (ext.charAt(0) != '.') {
                ret.append('.');
            }
            ret.append(ext);
        }

        return ret.toString();
    }

    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.error("Failed to get referrer property.", e);
                }
            }
        }
        return null;
    }

    /**
     * Override this method to implement the operation and return appropriate results.
     * @param request the requested that triggered the operation
     * @return a SocialOperationResult that contains the result of the operation.
     * @throws OperationException when an error occurs
     */
    protected abstract SocialOperationResult performOperation(SlingHttpServletRequest request)
        throws OperationException;

    class NonExistingResourceWrappingRequest extends SlingHttpServletRequestWrapper {
        final private Resource newResource;

        public NonExistingResourceWrappingRequest(final SlingHttpServletRequest wrappedRequest,
            final Resource resource) {
            super(wrappedRequest);
            this.newResource = resource;
        }

        @Override
        public Resource getResource() {
            return this.newResource;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy