DefaultGETServlet.java 10.7 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.reef.siren.Entity
 *  javax.servlet.ServletException
 *  org.apache.commons.lang.StringUtils
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.request.RequestParameter
 *  org.apache.sling.api.request.RequestParameterMap
 *  org.apache.sling.api.request.RequestPathInfo
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceMetadata
 *  org.apache.sling.api.resource.ResourceWrapper
 *  org.apache.sling.api.servlets.SlingSafeMethodsServlet
 *  org.apache.sling.commons.osgi.PropertiesUtil
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.rest.impl.servlet;

import com.adobe.granite.rest.ResourceManager;
import com.adobe.granite.rest.RestException;
import com.adobe.granite.rest.converter.ResourceConverter;
import com.adobe.granite.rest.converter.ResourceConverterContext;
import com.adobe.granite.rest.filter.Filter;
import com.adobe.granite.rest.filter.FilterFactory;
import com.adobe.granite.rest.filter.impl.CompositeFilter;
import com.adobe.granite.rest.filter.impl.FilterFactoryProvider;
import com.adobe.granite.rest.impl.ApiEndpointResourceProviderFactory;
import com.adobe.granite.rest.impl.SearchResultsResource;
import com.adobe.reef.siren.Entity;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.request.RequestParameterMap;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=1, label="Adobe Granite REST Default GET Servlet", description="Default servlet handling REST API GET requests")
@Service
@Properties(value={@Property(name="sling.servlet.methods", value={"GET"}, propertyPrivate=1), @Property(name="sling.servlet.extensions", value={"json"}, propertyPrivate=1), @Property(name="sling.servlet.resourceTypes", value={"granite/rest/core/resource"}, propertyPrivate=1), @Property(name="sling.servlet.prefix", intValue={0}, propertyPrivate=1)})
public class DefaultGETServlet
extends SlingSafeMethodsServlet {
    private static final int DEFAULT_LIMIT = 20;
    private static final int DEFAULT_OFFSET = 0;
    private static final boolean DEFAULT_ABSOLUT_URI = true;
    private static final String PREFIX_FILTER = "filter.";
    private final Logger log;
    @Property(label="Limit parameter default", description="Default value for the limit request parameter. Default is 20.", intValue={20})
    private static final String CFG_DEFAULT_LIMIT = "default.limit";
    private int defaultLimit;
    @Property(label="Use absolute URIs", description="Forces usage of absolutes URIs in the response. Default is true.", boolValue={1})
    private static final String CFG_USE_ABSOLUT_URI = "use.absolute.uri";
    private boolean useAbsoluteURI;
    @Reference
    private FilterFactoryProvider filterFactoryProvider;
    @Reference
    private ApiEndpointResourceProviderFactory apiEndpointResourceProviderFactory;

    public DefaultGETServlet() {
        this.log = LoggerFactory.getLogger(this.getClass());
        this.defaultLimit = 20;
    }

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        response.setContentType("application/vnd.siren+json");
        response.setCharacterEncoding("UTF-8");
        ResourceConverterContext context = this.getContext(request);
        try {
            Resource resource = this.unwrap(request.getResource());
            String query = request.getParameter("query");
            if (StringUtils.isNotBlank((String)query)) {
                ResourceManager resourceMgr = (ResourceManager)request.adaptTo(ResourceManager.class);
                Resource searchResult = this.performSearch(resourceMgr, resource, query);
                if (searchResult == null) {
                    response.setStatus(500);
                    return;
                }
                resource = searchResult;
            }
            long ims = request.getDateHeader("If-Modified-Since");
            long modificationTime = (long)(Math.floor((double)resource.getResourceMetadata().getModificationTime() / 1000.0) * 1000.0);
            if (ims < 0 || modificationTime > ims) {
                response.setDateHeader("Last-Modified", modificationTime);
                ResourceConverter renderer = (ResourceConverter)resource.adaptTo(ResourceConverter.class);
                if (renderer != null) {
                    Entity entity = (Entity)renderer.toEntity(context);
                    response.getWriter().write(entity.toString());
                } else {
                    response.setStatus(404);
                }
            } else {
                response.setStatus(304);
            }
        }
        catch (Exception e) {
            throw new ServletException(e.getMessage(), (Throwable)e);
        }
    }

    private Resource performSearch(ResourceManager resourceMgr, Resource resource, String query) throws UnsupportedOperationException, RestException {
        if (resourceMgr != null) {
            List<Resource> results = resourceMgr.find(resource, query);
            return new SearchResultsResource(resource, resource.getPath(), results);
        }
        return null;
    }

    private CompositeFilter<Resource> getFilterForRequest(SlingHttpServletRequest request) {
        CompositeFilter filter = new CompositeFilter();
        for (Map.Entry parameter : request.getRequestParameterMap().entrySet()) {
            String paramName = (String)parameter.getKey();
            if (!paramName.startsWith("filter.")) continue;
            String suffix = StringUtils.removeStart((String)paramName, (String)"filter.");
            String value = ((RequestParameter[])parameter.getValue())[0].getString();
            FilterFactory filterFactory = this.filterFactoryProvider.getFilterFactory(suffix);
            if (filterFactory != null) {
                Filter<Resource> specificFilter = filterFactory.getFilter(value);
                filter.addFilter(specificFilter);
                continue;
            }
            this.log.warn("Filter with suffix {} could not be found.", (Object)suffix);
        }
        return filter;
    }

    private ResourceConverterContext getContext(SlingHttpServletRequest request) {
        ResourceConverterContext context = new ResourceConverterContext();
        context.setLimit(this.getLimit(request));
        context.setOffset(this.getOffset(request));
        context.setFilter(this.getFilterForRequest(request));
        context.setShowAllProperties(this.getShowAllProperties(request));
        context.setShowProperties(this.getShowProperties(request));
        context.setScheme(request.getScheme());
        context.setServerName(request.getServerName());
        context.setServerPort(request.getServerPort());
        context.setContextPath(request.getContextPath());
        context.setRequestPathInfo(request.getRequestPathInfo());
        context.setParameters(request.getParameterMap());
        context.setAbsolutURI(this.useAbsoluteURI);
        return context;
    }

    private int getLimit(SlingHttpServletRequest request) {
        int limit = this.defaultLimit;
        String s = request.getParameter("limit");
        if (s != null && !"".equals(s)) {
            limit = Integer.parseInt(s);
        }
        return limit;
    }

    private int getOffset(SlingHttpServletRequest request) {
        int offset = 0;
        String s = request.getParameter("offset");
        if (s != null && !"".equals(s)) {
            offset = Integer.parseInt(s);
        }
        return offset;
    }

    private boolean getShowAllProperties(SlingHttpServletRequest request) {
        boolean showAll = false;
        String value = request.getParameter("showAllProperties");
        if (value != null) {
            showAll = Boolean.parseBoolean(value);
        }
        return showAll;
    }

    private String[] getShowProperties(SlingHttpServletRequest request) {
        return request.getParameterValues("showProperty");
    }

    private Resource unwrap(Resource resource) {
        Resource result = resource;
        while (result instanceof ResourceWrapper) {
            result = ((ResourceWrapper)result).getResource();
        }
        return result;
    }

    @Activate
    protected void activate(ComponentContext context) {
        Dictionary dict = context.getProperties();
        this.defaultLimit = PropertiesUtil.toInteger(dict.get("default.limit"), (int)20);
        this.useAbsoluteURI = PropertiesUtil.toBoolean(dict.get("use.absolute.uri"), (boolean)true);
    }

    protected void bindFilterFactoryProvider(FilterFactoryProvider filterFactoryProvider) {
        this.filterFactoryProvider = filterFactoryProvider;
    }

    protected void unbindFilterFactoryProvider(FilterFactoryProvider filterFactoryProvider) {
        if (this.filterFactoryProvider == filterFactoryProvider) {
            this.filterFactoryProvider = null;
        }
    }

    protected void bindApiEndpointResourceProviderFactory(ApiEndpointResourceProviderFactory apiEndpointResourceProviderFactory) {
        this.apiEndpointResourceProviderFactory = apiEndpointResourceProviderFactory;
    }

    protected void unbindApiEndpointResourceProviderFactory(ApiEndpointResourceProviderFactory apiEndpointResourceProviderFactory) {
        if (this.apiEndpointResourceProviderFactory == apiEndpointResourceProviderFactory) {
            this.apiEndpointResourceProviderFactory = null;
        }
    }
}